【JS】事件传播--事件捕获/冒泡

JavaScript 中的 事件冒泡(Event Bubbling) 和 事件捕获(Event Capturing) 是 DOM 事件传播机制的两个阶段。理解它们对事件监听、委托和防止冲突至关重要。


什么是事件传播?

三个阶段:

  1. 捕获阶段(Capturing Phase)
  2. 目标阶段(Target Phase)
  3. 冒泡阶段(Bubbling Phase)

🔄 三个阶段图示:

假设 HTML 结构如下:

bash 复制代码
<div id="outer">
  <button id="inner">Click me</button>
</div>

点击按钮时,事件传播顺序:

markdown 复制代码
1. document
2. html
3. body
4. #outer
5. #inner   ← 【目标阶段】
6. #outer
7. body
8. html
9. document

如何监听不同阶段的事件?

使用 addEventListener 时,第三个参数可以控制监听的是捕获阶段还是冒泡阶段:

arduino 复制代码
// 捕获阶段
outer.addEventListener("click", handler, true);

// 冒泡阶段(默认)
outer.addEventListener("click", handler); // 等价于 false

🛑 如何阻止事件传播?

✅ 阻止冒泡

csharp 复制代码
event.stopPropagation();

✅ 阻止默认行为(如点击链接跳转)

csharp 复制代码
event.preventDefault();

⚠️ 面试常见考点总结

概念 捕获(Capturing) 冒泡(Bubbling)
顺序 从外向内(父 → 子) 从内向外(子 → 父)
是否默认启用 ❌(需手动传 true) ✅ 默认启用
用途 少见、用于特定控制场景 常用于事件委托

📝面试回答模板:

JS 的事件传播分为捕获、目标和冒泡三个阶段。事件默认是从外层向目标元素传播(捕获阶段),然后从目标向外传播(冒泡阶段)。我们通常监听冒泡阶段来做事件处理,也可以通过 addEventListener 的第三个参数控制监听阶段,并用 stopPropagation() 来阻止继续传播。


🤔你是不是不明白捕获阶段是用来干什么的,冒泡阶段是用来干什么的?

✅ 先讲结论:

阶段 用途(干什么) 实际开发中是否常用
捕获阶段 拦截事件到达目标元素之前的过程 ❌ 很少使用
冒泡阶段 处理已经发生的事件或用来"事件委托" ✅ 非常常用

用现实生活场景解释给你听:

想象你在商场(document)里,有一位顾客(用户)点了商场里某家店(button)的产品。

  • 捕获阶段: 商场保安从外往里拦截顾客(提前干预事件)
  • 目标阶段: 顾客抵达商店(事件目标元素)
  • 冒泡阶段: 顾客走出商场回家(事件往上传播)

🎯 捕获阶段:干嘛用?

虽然不常用,但可以用于一些高级拦截的场景:

✅ 用例:全局提前"拦截"用户行为

javascript 复制代码
document.addEventListener("click", e => {
  console.log("你点了什么东西,我先知道!");
}, true); // 捕获阶段

✅ 用例:阻止事件到达目标元素

javascript 复制代码
parent.addEventListener("click", (e) => {
  e.stopPropagation();
  console.log("我拦住了,子元素根本不会响应");
}, true); // 捕获阶段

🫧 冒泡阶段:干嘛用?

这是我们在前端开发中最常使用的阶段。

✅ 最主要用途:事件委托(Event Delegation)

例如:一个列表中动态插入很多按钮,你不需要给每个按钮都绑定点击事件。

javascript 复制代码
document.querySelector("ul").addEventListener("click", (e) => {
  if (e.target.tagName === "LI") {
    console.log("你点击了某个列表项", e.target.textContent);
  }
});
  • 效率高(只绑定一次)
  • 动态添加的元素也能响应

📌 总结:

  • 捕获: 提前处理、阻止传播(高级用法)
  • 冒泡: 用于绝大多数事件监听,尤其是事件委托
相关推荐
衍辉channel4 小时前
衍辉AI速递 10.14|谷歌发布Gemini 4 Argon模型等9条AI资讯
javascript
vipxieliang4 小时前
JavaScript 事件循环与任务队列:从 setTimeout 到 Promise
前端·javascript
SamDeepThinking5 小时前
synchronized 和 lock 有什么区别?
java·后端·面试
考研保研资料分享5 小时前
普通211核专业保研经验:清华预推免录取与北大、西交面试复盘
面试·职场和发展
人道领域5 小时前
【面试八股速通篇01】锁与并发工具
java·开发语言·面试·c#
Misnearch5 小时前
React中的回调
前端·javascript·react.js
考研保研资料分享6 小时前
2022数学保研经验:211专业第一的中科大、浙大、南开等五校考核复盘
面试
十年Java程序媛6 小时前
Redis 分布式锁 + GZIP 压缩缓存踩坑|高并发缓存真实线上复盘
java·开发语言·spring boot·redis·分布式·缓存·面试
Eider19987 小时前
大模型输出格式幻觉解决思路
开发语言·前端·javascript
丑陋小蚊子7 小时前
网申简历附件太大,先换模板还是压缩 PDF?
面试·求职招聘·大学生·简历·简历下载