事件冒泡与捕获
一、事件流基础:事件冒泡与捕获的起源
- 事件流概念
- 事件发生时在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()额外中断同节点事件。 - 应用场景:捕获适合全局控制,冒泡适合事件代理(减少内存占用),阻止方法用于避免事件干扰。
