事件冒泡是DOM默认行为,事件从目标元素逐层向上触发至根节点;事件委托利用冒泡机制,将监听器绑定在父元素上,通过event.target.closest()安全获取真正点击的子元素。

事件冒泡不是bug,是DOM默认行为
点击一个 你不用给每个 看似简单,但实际容易翻车。因为用户可能点的是 委托不是银弹。有些场景硬套反而增加复杂度或引入 bug。 立即学习“Java免费学习笔记(深入)”;,它的父 甚至 document 都会收到这个 click 事件——这不是意外,是浏览器按规范走的流程。事件从目标元素出发,逐层向上“冒”到根节点,中间每层只要绑了同类型监听器就会触发。
true 给 addEventListener() 第三个参数focus、blur、mouseenter、mouseleave 默认不冒泡event.stopPropagation(),别用已废弃的 event.cancelBubble = true
stopPropagation() 后,同一事件流中更上层的监听器(包括 document 上的)将完全收不到该事件事件委托就是“让爸爸代签收快递”
单独绑 click,而是把监听器挂在它们共同的父级 上,等点击发生后,靠 event.target 查出到底点的是哪个 ——这就是委托的本质。
event.target 是**真正被点击的元素**,可能是个 或 ,不是你期望的 ;常用 event.target.closest('li') 安全获取目标项appendChild() 或 innerHTML 加的 ,无需重新绑定event.target 的样式或属性,除非你确认它就是你要处理的节点类型
为什么不能只写
if (event.target.tagName === 'LI')
里的文字、图标或按钮,此时 event.target 是那个子元素,tagName 就不是 'LI' 了。document.getElementById('myList').addEventListener('click', function(event) {
// ❌ 危险:点到 li 里的 span 就失效
if (event.target.tagName === 'LI') {
console.log('OK');
}
// ✅ 推荐:向上找最近的 li
const item = event.target.closest('li');
if (item) {
console.log('Clicked item:', item.textContent);
}
});
closest() 兼容性好(IE 不支持,但现代项目基本可忽略);若需兼容老 IE,可用循环遍历 parentNode
event.currentTarget 判断目标——它永远是绑定监听器的那个父元素,不是你点的那个input 事件不冒泡,得用 change 或监听 input 的父容器并用 focusin/focusout 替代什么时候不该用事件委托










