在 JavaScript 中,事件传播分为三个阶段:捕获阶段(Capture Phase) 、目标阶段(Target Phase) 和 冒泡阶段(Bubble Phase) 。addEventListener
的第三个参数可以控制事件监听器是在捕获阶段还是冒泡阶段触发。
1. 捕获阶段(Capture Phase)
- 从外向内传播 :事件从最外层的祖先元素(
window
)向下逐级传递到目标元素。 - 监听方式 :将
addEventListener
的第三个参数设为true
或{ capture: true }
。 - 特点:先执行捕获阶段的监听器,再执行目标阶段的事件,最后执行冒泡阶段的监听器。
2. 冒泡阶段(Bubble Phase)
- 从内向外传播:事件从目标元素向上逐级传递到最外层的祖先元素。
- 默认行为 :如果
addEventListener
的第三个参数未设置或设为false
/{ capture: false }
,监听器会在冒泡阶段触发。 - 特点 :大多数事件默认支持冒泡(如
click
),但少数事件(如focus
)不冒泡。
区别总结
特征 | 捕获阶段 | 冒泡阶段 |
---|---|---|
传播方向 | 外层 → 目标元素(向下) | 目标元素 → 外层(向上) |
addEventListener |
第三个参数设为 true |
第三个参数为 false (默认) |
执行顺序 | 先于冒泡阶段 | 后于捕获阶段 |
常见用途 | 提前拦截事件(如权限检查) | 常规事件处理(如委托) |
代码示例
html
<div id="parent">
<div id="child">点击我</div>
</div>
<script>
const parent = document.getElementById('parent');
const child = document.getElementById('child');
// 捕获阶段监听(第三个参数为 true)
parent.addEventListener('click', () => {
console.log('父元素 - 捕获阶段');
}, true);
// 冒泡阶段监听(默认)
parent.addEventListener('click', () => {
console.log('父元素 - 冒泡阶段');
});
child.addEventListener('click', () => {
console.log('子元素 - 目标阶段');
});
</script>
输出结果(点击子元素时):
父元素 - 捕获阶段
子元素 - 目标阶段
父元素 - 冒泡阶段
应用场景
- 事件委托(冒泡阶段)
通过父元素监听子元素的事件(如动态生成的列表项)。 - 拦截操作(捕获阶段)
在事件到达目标前进行拦截(如权限验证、阻止默认行为)。
注意事项
- 使用
event.stopPropagation()
可阻止事件继续传播(捕获或冒泡)。 - 目标元素的事件监听器(如
child
)在目标阶段触发,与第三个参数无关。