addEventListener事件在父元素上绑定,目标为子元素。

15

我正在做一个小应用来学习ES6,但是我在使用addEventListener和父/子事件时遇到了问题。

我有一个菜单,由几个带有图像(头像)和一些文本的

组成。每个
都有一个data-id属性,以获取所点击元素的id,并在每一行上放置了addEventListener

<div class="row" data-id="1">
  <img src="avatar" />
  Lorem ipsum
</div>
...

并且js:

const rows = document.querySelectorAll('.row');
rows.forEach(row => row.addEventListener('click',selectRow));

function selectRow(e){
  var row = e.target;
  alert(row.dataset.id);
}

当我点击头像时出现问题,它会触发点击事件,但目标是图片元素而不是div,所以我无法获取data-id属性。

我已经尝试了很多方法(例如这个),但它会阻止在头像上点击时触发事件,因此并不是解决方案,因为头像是行的一部分,可能会被点击:S

我设置了一个jsfiddle来展示我的问题。任何帮助都将不胜感激:)

https://jsfiddle.net/igorosabel/o64b404y/1/


1
请使用本站的 Stack Snippets([<>] 按钮),而不是 jsFiddle,这样所有的代码、标记等都包含在问题中。虽然您的问题已经有足够的代码了,但如果您已经创建了可运行的示例,最好将其包含在内。 - T.J. Crowder
1个回答

18
它触发了点击事件,但目标是img元素,而不是div,所以我无法获取data-id属性。正确。target是事件的实际目标,无论您将事件挂钩在哪个元素上,都可能与实际目标不同,因为冒泡(在您的情况下,单击会从img冒泡到div)。您可以通过this(假设您让事件系统为处理程序设置this)或e.currentTarget获取您挂钩事件的元素。带有该更改的代码段中的您的fiddle:

const rows = document.querySelectorAll('.row');
rows.forEach(row => row.addEventListener('click',showId));

function showId(e){
  console.log("Using this:", this.dataset.id);
  console.log("Using e.currentTarget:", e.currentTarget.dataset.id);
}
.row{
  border: 1px solid #000;
  margin-bottom: 10px;
  padding: 10px;
}
<div class="row" data-id="1">
  <img src="https://placehold.it/100x100" />
  Lorem ipsum
</div>
<div class="row" data-id="2">
  <img src="https://placehold.it/100x100" />
  Lorem ipsum
</div>
<div class="row" data-id="3">
  <img src="https://placehold.it/100x100" />
  Lorem ipsum
</div>


1
只要您不使用箭头函数或绑定函数作为处理程序,就可以了(因为箭头函数会关闭this,而绑定函数会忽略它们被调用时的this)。事件处理系统在调用处理程序时将e.currentTarget用作this。@IñigoGorosabel::-) - T.J. Crowder
对于箭头函数,我们必须使用选择器来获取this。在您的函数中,它将是row - WBGUY001
@WBGUY001 我不明白你在那里说什么...? - T.J. Crowder
对于箭头函数,rows.forEach(row => row.addEventListener('click',() => { console.log(row) })); - WBGUY001
@WBGUY001 - 是的,他们也可以这样做,但没有特别的理由去这样做,而且它会为每个元素创建一个单独的函数。 - T.J. Crowder

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接