事件冒泡与捕获
一、事件流基础:事件冒泡与捕获的起源
- 事件流概念
- 事件发生时在DOM节点上的传播顺序,触发一个节点的事件会连锁触发相关节点的事件。
- 两种对立模型
- 事件捕获(微软提出):事件从文档根节点(如
document
)开始,逐级向目标节点传播,父节点先于子节点触发事件。 - 事件冒泡(网景提出):事件从目标节点开始,逐级向根节点传播,子节点先于父节点触发事件。
- 事件捕获(微软提出):事件从文档根节点(如
- W3C统一模型
- 采用“先捕获后冒泡”的流程:事件先从根节点捕获到目标节点(捕获阶段),再从目标节点冒泡回根节点(冒泡阶段)。
二、事件捕获(Event Capturing)
- 传播顺序
- 从DOM树顶层(如
document
→html
→body
)逐步向下到目标节点。 - 例:点击
<a>
标签时,捕获顺序为document
→div
→p
→a
。
- 从DOM树顶层(如
- 绑定事件方法
- 使用
addEventListener
,第三个参数设为true
:
element.addEventListener("click", handler, true); // 捕获阶段触发
- 使用
三、事件冒泡(Event Bubbling)
- 传播顺序
- 从目标节点开始,逐级向上到根节点。
- 例:点击
<a>
标签时,冒泡顺序为a
→p
→div
→body
→document
。
- 绑定事件默认行为
addEventListener
第三个参数默认false
(冒泡阶段触发),或直接使用onclick
等属性绑定(默认冒泡):
element.addEventListener("click", handler); // 等价于传入false,冒泡阶段触发 element.onclick = handler; // 默认冒泡阶段触发
四、阻止事件传播
- 阻止捕获和冒泡
event.stopPropagation()
:终止事件在捕获和冒泡阶段的传播,后续节点的事件不再触发,但不影响当前节点的其他事件处理程序。
- 阻止同一节点的后续事件
event.stopImmediatePropagation()
:不仅阻止传播,还会中断当前节点上同一事件的其他事件处理程序执行(即使已绑定的事件)。
五、阻止默认事件行为
- 方法
event.preventDefault()
:取消事件的默认行为(如链接跳转、表单提交等)。- 兼容性:IE9及以下不支持,需用
event.returnValue = false
替代。
- 示例
// 阻止链接跳转 link.addEventListener("click", function(event) {event.preventDefault(); // 标准浏览器event.returnValue = false; // IE9及以下兼容 });
六、核心知识点对比
特性 | 事件捕获 | 事件冒泡 |
---|---|---|
传播方向 | 根节点 → 目标节点 | 目标节点 → 根节点 |
绑定参数 | addEventListener(..., true) | addEventListener(..., false) (默认) |
典型应用 | 全局事件监听(如点击空白处关闭弹窗) | 事件代理(通过父节点统一处理子节点事件) |
阻止方法 | 作用 |
---|---|
stopPropagation() | 阻止事件向父/子节点传播 |
stopImmediatePropagation() | 阻止传播并中断当前节点同事件的后续处理 |
preventDefault() | 阻止事件默认行为(如表单提交、链接跳转) |
总结
- 事件流流程:先捕获(根→目标),后冒泡(目标→根)。
- 事件绑定:通过
addEventListener
的第三个参数控制阶段(true
=捕获,false
=冒泡)。 - 事件控制:
stopPropagation()
阻止传播,preventDefault()
阻止默认行为,stopImmediatePropagation()
额外中断同节点事件。 - 应用场景:捕获适合全局控制,冒泡适合事件代理(减少内存占用),阻止方法用于避免事件干扰。