addeventlistener 的 capture 参数设为 true 时监听捕获阶段事件,即事件从 document 向目标元素传播时触发;此时可提前调用 preventdefault() 阻断默认行为,且 this 指向绑定元素、event.target 指向原始触发元素。

addEventListener 的 capture 参数设为 true 时到底监听什么
它让事件监听器在捕获阶段(从 document → html → body → 目标父元素 → 目标元素)触发,而不是默认的冒泡阶段。也就是说,哪怕你绑在子元素上,只要 capture 为 true,它会在事件“下来”的路上就响应,早于目标元素自身的监听器执行。
什么时候必须用 capture:阻止默认行为但又不能等冒泡
典型场景是:想在父容器拦截某个子元素的点击,提前调用 event.preventDefault(),但子元素自己没监听、或监听了却没阻止——此时如果父元素用默认(冒泡)模式监听,等事件传到它那已经晚了,defaultPrevented 可能已失效(比如 click 触发链接跳转、表单提交)。
-
capture: true让父元素在捕获阶段就能调用event.preventDefault(),有效阻断后续行为 - 常见于封装的模态框、下拉菜单、权限拦截容器:用户点内部按钮,但容器层要先判断是否允许操作
- 注意:
preventDefault()在捕获阶段调用是完全合法且被规范支持的
capture 为 true 时,this 和 event.target 的指向差异
即便监听器绑在子元素上,只要 capture 是 true,它在捕获阶段经过该子元素时就会触发——此时 this 是绑定的元素(即子元素),但 event.target 是最开始触发事件的那个元素(比如你点的是孙元素,target 就是孙元素)。这点和冒泡阶段一致,但容易误以为“捕获=事件源变了”。
div#parent.addEventListener('click', e => {
console.log('this:', this.id); // "child"
console.log('e.target:', e.target.id); // "grandchild"(实际被点击的)
}, true); // ← capture: true
别混淆 capture 和 useCapture 参数名
第三个参数不是叫 capture,而是 useCapture,类型是布尔值。写成 { capture: true } 是新版对象参数写法,但兼容性有坑:
- 老浏览器(IE9–)不支持对象参数,只认三个参数形式:
addEventListener(type, handler, useCapture) - Chrome 88+ 才开始支持
{ capture: true, passive: false }这种写法 - 混用风险:若同时传
true和{ capture: false },后者会覆盖前者,但多数运行时不会报错,只会静默失效
生产环境建议统一用三参数形式,除非明确不需要 IE/旧 Safari 支持。
捕获阶段监听真正难的不是语法,而是事件流时机判断——你得清楚当前事件是否已被更外层的捕获监听器拦截过,以及 stopPropagation() 在捕获路径中调用后,是否还会影响后续冒泡。这个链路一旦嵌套三层以上,调试起来几乎只能靠 console.log(event.eventPhase) 硬看。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











