JavaScript 事件流:事件捕获和事件冒泡
一、什么是事件流
当用户与网页交互时(如点击按钮),事件并不是只在触发元素上发生,而是会经历一个完整的传播过程,这个过程称为事件流。
二、事件流的三个阶段
(1)捕获阶段:从最外层的 window 对象向内传播到目标元素
(2)目标阶段:事件到达目标元素本身
(3)冒泡阶段:从目标元素向外传播回 window 对象
三、事件捕获(Event Capturing)
事件捕获是从外向内的传播过程,现代浏览器支持通过 addEventListener 的第三个参数来监听捕获阶段的事件。
document.getElementById('outer').addEventListener('click',() => console.log('Outer - Capture'),true // true 表示在捕获阶段触发
);
四、事件冒泡(Event Bubbling)
事件冒泡是从内向外的传播过程,这是默认的事件传播方式。
document.getElementById('inner').addEventListener('click',() => console.log('Inner - Bubble')// 第三个参数默认是 false,表示在冒泡阶段触发
);
五、完整示例
<div id="outer"><div id="middle"><div id="inner">Click me</div></div>
</div><script>
// 捕获阶段
document.getElementById('outer').addEventListener('click', () => console.log('Outer - Capture'), true);
document.getElementById('middle').addEventListener('click', () => console.log('Middle - Capture'), true);
document.getElementById('inner').addEventListener('click', () => console.log('Inner - Capture'), true);// 冒泡阶段
document.getElementById('outer').addEventListener('click', () => console.log('Outer - Bubble'));
document.getElementById('middle').addEventListener('click', () => console.log('Middle - Bubble'));
document.getElementById('inner').addEventListener('click', () => console.log('Inner - Bubble'));
</script>
点击 inner 元素时的输出顺序:Outer - Capture
Middle - Capture
Inner - Capture
Inner - Bubble
Middle - Bubble
Outer - Bubble
六、阻止事件传播
使用 event.stopPropagation() 可以阻止事件继续传播:
document.getElementById('middle').addEventListener('click', (e) => {console.log('Middle - Bubble');e.stopPropagation(); // 阻止事件继续冒泡
});
七、实际应用场景
(1)事件委托:利用冒泡特性,将事件监听器添加到父元素而非每个子元素
(2)事件节流与防抖:在捕获或冒泡阶段处理高频触发事件
(3)组件封装:在框架中利用事件流实现父子组件通信
八、注意事项
(1)IE8 及以下只支持事件冒泡
(2)某些事件(如 focus、blur)不支持冒泡
(3)使用 event.target 获取实际触发事件的元素