事件委托怎么拿不到动态添加的子元素数据?
我用事件委托给一个 ul 绑定了点击事件,想通过 e.target 获取 li 里的 data-id,但新 append 进去的 li 点击后拿不到属性,老的却可以。是不是我写法有问题?
我试过把事件监听器加在 document 上也不行,代码大概是这样:
document.querySelector('ul').addEventListener('click', function(e) {
if (e.target.tagName === 'LI') {
console.log(e.target.dataset.id);
}
});
e.target.tagName === 'LI',但点击事件可能发生在 li 的子元素上(比如里面的 span 或文本节点)。直接用这个:closest()方法会往上找最近的 li 元素,不管你是点到 li 本身还是里面的子元素都能正确获取。比直接判断 tagName 靠谱多了,我调试动态元素经常用这招。e.target指向的是你点击的最内层元素。如果你的 li 里面有其他元素,比如 span 或者文字节点,点击的时候
e.target就会是那个 span,而不是 li。所以你的tagName === 'LI'判断直接就挂了,根本走不到 log 那一行。老的 li 能拿到数据,估计是因为里面没有子元素,点击直接命中 li 本身。
解决方法很简单,用
closest()往上找:这样不管你点的是 li 本身还是它里面的 span、div、图标什么的,都能正确找到对应的 li 元素。
另外还有个细节要注意,
closest()会从当前元素开始往上找,包括元素自己,所以不用再额外判断 tagName 了。如果点击的是 ul 外面的区域,closest('li')会返回 null,加个判断就行。这个方法对动态添加的元素完全没问题,事件委托本来就是干这个事的。