Skip to content

事件冒泡与事件捕获

✍️天畅🕐2025-05-17

你以为事件只是绑定了就完事?其实它背后还有“来龙去脉”!

🔍 什么是事件传播?

当你在网页中点击一个按钮时,这个“事件”并不会直接只作用于这个按钮,而是沿着 DOM 树进行传播。这个传播过程有三个阶段:

📶 事件传播的三个阶段

  1. 捕获阶段(Capturing Phase):事件从 window 一路向下传递到目标元素。

  2. 目标阶段(Target Phase):事件到达真正被点击的目标元素。

  3. 冒泡阶段(Bubbling Phase):事件从目标元素向上传递到 window

🔁 示例结构

html
<body>
  <div id="outer">
    <div id="inner">
      <button id="btn">Click me</button>
    </div>
  </div>
</body>

点击 #btn 后的事件传播顺序如下:

window ↓
document ↓
html ↓
body ↓
#outer ↓
#inner ↓
#btn      ← 目标阶段
#inner ↑
#outer ↑
body ↑
html ↑
document ↑
window ↑

🧪 示例代码:冒泡与捕获监听对比

js
// 捕获阶段
outer.addEventListener('click', () => {
  console.log('outer capture');
}, true);

// 冒泡阶段
outer.addEventListener('click', () => {
  console.log('outer bubble');
});

输出顺序:

outer capture
outer bubble

🧠 关键点记忆

|比较项|捕获(Capturing)|冒泡(Bubbling)| |||| |方向|从外到内(顶层 → 目标)|从内到外(目标 → 顶层)| |是否默认启用|❌ 否(需设置为第三个参数 true)|✅ 是| |使用场景|特定顺序控制,如拦截早期事件|最常见,用于事件委托| |是否可中断|否(不能中断捕获本身)|✅ event.stopPropagation()| |常配合|window、document 捕获|事件委托、组件冒泡|

🧯 如何中断传播?

js
// 阻止继续冒泡
event.stopPropagation();

// 阻止默认行为(如 <a> 跳转)
event.preventDefault();

🎯 实战应用:事件委托

js
document.getElementById('list').addEventListener('click', (e) => {
  if (e.target.tagName === 'LI') {
    console.log('点击了某个列表项');
  }
});
  • 使用冒泡机制,不必给每个子元素绑定事件

  • 适用于动态添加元素的情况

🧩 总结一句话:

事件是从外往内捕获,从内往外冒泡的。默认是冒泡监听,要捕获得手动指定。