JavaScript中的事件流与事件模型
字数 361 2025-11-11 20:15:48
JavaScript中的事件流与事件模型
事件流描述的是事件在DOM结构中传播的路径和顺序。理解事件流对正确处理事件至关重要。
事件流的三个阶段
- 捕获阶段:事件从window对象向下传播到目标元素
- 目标阶段:事件到达目标元素
- 冒泡阶段:事件从目标元素向上传播回window对象
事件监听器的使用
// 添加事件监听器(默认使用冒泡阶段)
element.addEventListener('click', handler);
// 使用捕获阶段
element.addEventListener('click', handler, true);
// 或
element.addEventListener('click', handler, {capture: true});
完整的事件传播示例
<div id="grandparent">
<div id="parent">
<button id="child">点击我</button>
</div>
</div>
<script>
const grandparent = document.getElementById('grandparent');
const parent = document.getElementById('parent');
const child = document.getElementById('child');
// 捕获阶段处理
grandparent.addEventListener('click', (e) => {
console.log('爷爷元素 - 捕获阶段');
}, true);
parent.addEventListener('click', (e) => {
console.log('父元素 - 捕获阶段');
}, true);
// 目标阶段处理
child.addEventListener('click', (e) => {
console.log('子元素 - 目标阶段');
});
// 冒泡阶段处理
parent.addEventListener('click', (e) => {
console.log('父元素 - 冒泡阶段');
});
grandparent.addEventListener('click', (e) => {
console.log('爷爷元素 - 冒泡阶段');
});
</script>
点击按钮后的输出顺序:
- 爷爷元素 - 捕获阶段
- 父元素 - 捕获阶段
- 子元素 - 目标阶段
- 父元素 - 冒泡阶段
- 爷爷元素 - 冒泡阶段
事件对象的重要属性和方法
element.addEventListener('click', function(event) {
// 阻止事件继续传播
event.stopPropagation();
// 阻止默认行为
event.preventDefault();
// 事件当前所在的元素
console.log(event.currentTarget);
// 实际触发事件的元素
console.log(event.target);
// 事件传播的阶段
console.log(event.eventPhase); // 1:捕获 2:目标 3:冒泡
});
事件委托模式
利用事件冒泡机制,在父元素上处理子元素的事件:
// 传统方式(为每个子元素添加监听器)
document.querySelectorAll('.item').forEach(item => {
item.addEventListener('click', handleClick);
});
// 事件委托方式(只需一个监听器)
document.getElementById('container').addEventListener('click', (e) => {
if (e.target.classList.contains('item')) {
handleClick(e);
}
});
实际应用场景
- 动态内容处理:适合动态添加的元素
- 性能优化:减少事件监听器数量
- 内存管理:避免内存泄漏
理解事件流能帮助你更精确地控制事件处理,写出更健壮的交互代码。