事件触发顺序
DOM 事件的捕获、目标、冒泡三个阶段
问题
DOM 事件触发时,经历哪些阶段?事件处理函数的执行顺序是什么?
解答
事件传播的三个阶段
- 捕获阶段:从
window向下传播到目标元素 - 目标阶段:到达目标元素
- 冒泡阶段:从目标元素向上传播到
window
window
│
▼ 捕获阶段
document
│
▼
<html>
│
▼
<body>
│
▼
<div>
│
▼
<button> ← 目标阶段
│
▼ 冒泡阶段
(向上返回)
代码示例
<!DOCTYPE html>
<html>
<body>
<div id="outer">
<button id="inner">点击我</button>
</div>
<script>
const outer = document.getElementById('outer');
const inner = document.getElementById('inner');
// 捕获阶段触发(第三个参数为 true)
outer.addEventListener('click', () => {
console.log('outer 捕获');
}, true);
inner.addEventListener('click', () => {
console.log('inner 捕获');
}, true);
// 冒泡阶段触发(第三个参数为 false 或省略)
outer.addEventListener('click', () => {
console.log('outer 冒泡');
}, false);
inner.addEventListener('click', () => {
console.log('inner 冒泡');
}, false);
// 点击 button 输出顺序:
// outer 捕获
// inner 捕获
// inner 冒泡
// outer 冒泡
</script>
</body>
</html>
目标阶段的特殊情况
在目标元素上,事件处理函数按注册顺序执行,不区分捕获和冒泡:
const btn = document.getElementById('btn');
// 先注册冒泡
btn.addEventListener('click', () => {
console.log('冒泡');
}, false);
// 后注册捕获
btn.addEventListener('click', () => {
console.log('捕获');
}, true);
// 点击 btn 输出:
// 冒泡
// 捕获
// (按注册顺序,而非先捕获后冒泡)
阻止传播
element.addEventListener('click', (e) => {
// 阻止事件继续传播(捕获或冒泡)
e.stopPropagation();
// 阻止传播,同时阻止当前元素上其他同类型事件处理函数执行
e.stopImmediatePropagation();
});
事件委托应用
利用冒泡机制,在父元素上统一处理子元素事件:
document.getElementById('list').addEventListener('click', (e) => {
// 判断实际点击的元素
if (e.target.tagName === 'LI') {
console.log('点击了:', e.target.textContent);
}
});
关键点
- 事件传播顺序:捕获 → 目标 → 冒泡
addEventListener第三个参数:true捕获阶段触发,false(默认)冒泡阶段触发- 目标元素上的事件按注册顺序执行,不区分捕获冒泡
stopPropagation()阻止传播,stopImmediatePropagation()还能阻止同元素其他处理函数- 事件委托利用冒泡机制,减少事件绑定数量
目录