addEventListener 的第三个参数中 capture: true 使监听器在捕获阶段触发,即事件从 document 向目标元素逐层向下传播时执行;默认 false 则在冒泡阶段触发。

在 JavaScript 中,addEventListener 的第三个参数(即 options)可以是一个布尔值或一个配置对象。当传入 { capture: true } 时,事件监听器会在**捕获阶段**被触发;默认为 false(或省略),则在**冒泡阶段**触发。
capture 选项的作用机制
DOM 事件流分为三个阶段:捕获 → 目标 → 冒泡。默认情况下,监听器只响应目标和冒泡阶段。开启 capture: true 后,监听器会提前在捕获阶段(从 document 向目标元素逐层向下)执行。
- 捕获阶段:事件从最外层祖先(如
document)开始,逐级向目标元素传播 - 目标阶段:事件到达绑定的目标元素本身
- 冒泡阶段:事件从目标元素向上逐级回传到祖先节点
如何正确使用 capture 选项
推荐使用对象形式传参,语义清晰且支持其他选项(如 once、passive):
-
elem.addEventListener('click', handler, { capture: true })—— 捕获阶段触发 -
elem.addEventListener('click', handler, { capture: false })—— 冒泡阶段触发(等价于false) -
elem.addEventListener('click', handler, true)—— 旧式写法,true等价于{ capture: true }
捕获与冒泡共存时的执行顺序
同一元素上同时绑定捕获和冒泡监听器时,执行顺序严格按事件流阶段进行:
立即学习“Java免费学习笔记(深入)”;
- 先执行所有祖先元素上的捕获监听器(由外向内)
- 再执行目标元素上的捕获监听器(即使它自己设了
capture: true) - 然后执行目标元素上的冒泡监听器(
capture: false或未指定) - 最后执行祖先元素上的冒泡监听器(由内向外)
注意:同一个元素上,无论 capture 值如何,目标阶段的监听器都会在该元素上触发一次;但捕获监听器不会在冒泡阶段重复触发,反之亦然。
实际应用场景举例
捕获模式常用于需要“提前拦截”事件的场景:
- 全局快捷键监听(如
Esc关闭弹窗),在document上用捕获确保不被子元素stopPropagation()阻断 - 组件封装时,在父容器监听子元素的事件,避免依赖子元素主动冒泡
- 实现自定义事件委托,统一在父级处理,且希望在子元素处理前介入(例如权限校验、日志记录)


















