JavaScript事件处理核心是事件流(捕获→目标→冒泡)与监听器执行时机的耦合;默认绑定在冒泡阶段,capture/once/passive/signal等选项提供精细控制;事件委托依赖冒泡和event.target,移除监听器须用相同函数引用。

JavaScript 事件处理不是“注册完就触发”那么简单,核心在于事件流(捕获→目标→冒泡)和监听器执行时机的耦合关系。不理解这个机制,event.stopPropagation() 会失效,addEventListener() 的第三个参数容易配错,动态绑定的事件也可能漏掉。
事件流分三阶段:捕获、目标、冒泡
点击一个嵌套在 现代浏览器支持传入 注意: 立即学习“Java免费学习笔记(深入)”; 给父容器绑定一个监听器,靠 最容易被忽略的是:事件委托中动态增删 DOM 后,别以为“委托”就一劳永逸——如果新插入的元素需要不同行为,仍得靠 ,事件实际按顺序经过:document → body → div → button(捕获),停在 button(目标),再原路返回(冒泡)。默认所有 addEventListener() 绑定在冒泡阶段。
true 才进,比如 el.addEventListener('click', handler, true)
event.eventPhase 值为 2
el.addEventListener('click', handler) 或 false 都走这里
addEventListener 的第三个参数不只是布尔值options 对象,比单纯用 true/false 更精细:
{ capture: true } 等价于旧写法的 true
{ once: true } 表示监听器只执行一次,自动解绑,适合初始化逻辑{ passive: true } 告诉浏览器“我不会调 preventDefault()”,可提升滚动性能(尤其移动端){ signal: abortController.signal } 允许外部统一取消监听,适合组件卸载场景passive: true 后再调 event.preventDefault() 不报错但无效,Chrome 控制台会警告 “Unable to preventDefault inside passive event listener”。事件委托靠的是冒泡 +
event.target 判定event.target 区分真正被点中的子元素,而不是给每个子元素单独绑定——这是性能关键。
event.target 获取触发事件的最深节点(比如你点的是 )event.currentTarget 获取当前绑定监听器的元素(比如你绑在 上)if (event.target.matches('button.delete')) { ... }
parentNode 层层向上查,改用 event.target.closest('li') 更健壮移除监听器必须用完全相同的函数引用
removeEventListener 不认函数体,只认函数地址。匿名函数、箭头函数无法被精确移除:el.addEventListener('click', () => console.log('ok'));
el.removeEventListener('click', () => console.log('ok')); // ❌ 失效,两个箭头函数是不同引用
const handler = () => {...}; add..., remove...
{ once: true } 替代手动移除target 判断分支,而不是重新绑定。











