父级上的事件,单击子级(事件冒泡)

Event on parent, click child (event bubbling)

本文关键字:事件 单击      更新时间:2023-09-26

我有一个人员搜索脚本,可以在您键入时显示建议。结果的结构大致如下:

<div  id="peopleResults">
  <div class="resultHolder">
    <div data-userid="ABC123" class="person">
        <div class="name">Last, First</div>
        <div class="title">Job Title</div>
        <a class="email" href="mailto:person@company.com">person@company.com</a><span class="phone">12345</span>
    </div>
    <!-- more people... -->
  </div>
</div>

由于人员列表在您键入时会发生变化,因此到目前为止,我一直在使用 JQuery 的 live(( 函数自动将点击事件绑定到所有 .person 元素。这是已弃用且不好的做法,因此我正在尝试更新代码。

看到我可以使用这样的东西:

$('#peopleResults').on('click', '.person', function(){
    // handle the click
})

但是我想更多地了解如何在vanilla javascript中处理这个问题。我认为当单击带有单击事件的项目的子项时,该事件会在元素中"冒泡",当它击中 .person 元素时我可以捕获它。请原谅草率的代码,但像这样:

document.getElementById('peopleResults').addEventListener('click', function(e){
    if(e.target.classList.contains('person')) {
        // handle click 
    }
});

我过去做过类似的事情,但通常是链接。(在这种情况下,.person 不能是链接,因为它包含电子邮件链接。

所以在这种情况下它不起作用。如果我在 .person 中点击 .name,目标是 .name。

这似乎是一些基本的东西,只是没有在我的大脑中点击。在 JavaScript 中处理这个问题的典型方法是什么?

您可以为

所需目标的所有子级设置pointer-events none

.person > * {
  pointer-events: none;
}

这样event.target将是一个.person元素,而不是它的后代之一。

document.getElementById('peopleResults').addEventListener('click', function(e){
  if(e.target.classList.contains('person')) {
    alert('Person clicked');
  }
});
.person > * {
  pointer-events: none;
}
<div  id="peopleResults">
  <div class="resultHolder">
    <div data-userid="ABC123" class="person">
      <div class="name">Last, First</div>
      <div class="title">Job Title</div>
      <a class="email" href="mailto:person@company.com">person@company.com</a><span class="phone">12345</span>
    </div>
    <!-- more people... -->
  </div>
</div>

请注意,此方法将破坏.person内部交互元素(例如链接(的功能。

使用 jQuery 事件时,你会得到两个你应该熟悉的属性:

  1. target
  2. currentTarget

使用事件委托(意味着捕获父元素上的事件(时,target将是最初触发事件的元素,而currentTarget将是捕获事件的元素。

请考虑以下代码示例:

$('#peopleResults').on('click', '.person', function(e) {
    if ($(e.currentTarget).hasClass('person')) console.log('yay!');
});

PS - 不使用事件委托时,两个属性都应指向同一元素。

有关当前目标的更多信息。