1.事件流:捕获与冒泡

查看飞书原文 ↗2,361 字符
1. 核心心智模型​
​
当你在网页上点击一个元素时,这个“点击事件”并不仅仅发生在该元素上。它经历了一个完整的旅程,这个旅程被称为 DOM 事件流 (Event Flow)。​
​
想象一下一个三层嵌套的盒子:div (外层) > p (中层) > span (内层)。当你点击最里面的 span 时:​
​
1.
捕获阶段 (Capturing Phase): 浏览器会从最外层的祖先 window 开始,像一个“指挥官”下达命令一样,逐级向下“探查”,经过 document、<html>、<body>、div、p,最终到达你点击的目标 span。这个从外到内的过程就是捕获阶段。​
2.
目标阶段 (Target Phase): 事件到达了它的最终目的地——你实际点击的 span 元素。事件在这里被触发。​
3.
冒泡阶段 (Bubbling Phase): 事件完成任务后,开始“汇报工作”。它会从 span 开始,逐级向上“冒泡”,经过 p、div,一直到 window。这个从内到外的过程就是冒泡阶段。​
​
一句话总结:事件先从外到内“潜入”(捕获),到达目标后,再从内到外“浮出”(冒泡)。​
​
默认情况下,我们用 addEventListener 添加的监听器只在 冒泡阶段 执行。​
​
2. 示例:在控制台直观展示事件流​
​
让我们用代码来直观地看到这个完整的路径。​
​
HTML 结构:​
​
<div class="grandparent">
  Grandparent
  <div class="parent">
    Parent
    <div class="child">Child</div>
  </div>
</div>
​
CSS (仅为视觉效果):​
​
div {
  padding: 30px;
  border: 2px solid #666;
  text-align: center;
  font-family: sans-serif;
}
.grandparent { background-color: #fdd; }
.parent { background-color: #dfd; }
.child { background-color: #ddf; }
​
JavaScript 实现:​
​
我们将为每一个 div 都添加两个监听器:​
•
一个在捕获阶段触发 ({ capture: true })​
•
一个在冒泡阶段触发 (默认)​
​
const grandparent = document.querySelector('.grandparent');
const parent = document.querySelector('.parent');
const child = document.querySelector('.child');

// --- 捕获阶段监听器 ---
grandparent.addEventListener('click', () => {
  console.log('Grandparent - 捕获阶段');
}, { capture: true });

parent.addEventListener('click', () => {
  console.log('Parent - 捕获阶段');
}, { capture: true });

child.addEventListener('click', () => {
  console.log('Child - 捕获阶段 (也会在目标阶段触发)');
}, { capture: true });


// --- 冒泡阶段监听器 ---
grandparent.addEventListener('click', () => {
  console.log('Grandparent - 冒泡阶段');
});

parent.addEventListener('click', () => {
  console.log('Parent - 冒泡阶段');
});

child.addEventListener('click', () => {
  console.log('Child - 冒泡阶段');
});
​
运行与分析:​
​
现在,打开浏览器的开发者工具,点击最内层的蓝色 Child 区域。你会在控制台看到以下输出:​
​
// ↓ 从外到内(捕获阶段)
Grandparent - 捕获阶段
Parent - 捕获阶段
Child - 捕获阶段 (也会在目标阶段触发)

// ↓ 从内到外(冒泡阶段)
Child - 冒泡阶段
Parent - 冒泡阶段
Grandparent - 冒泡阶段
​
结果分析:​
​
1.
事件开始下沉: 点击发生后,事件流从 grandparent 开始,触发了它的捕获监听器。​
2.
继续下沉: 事件流到达 parent,触发了它的捕获监听器。​
3.
到达目标: 事件流到达 child。在目标元素上,监听器触发的顺序是按代码注册的顺序,所以先触发了捕获监听器,然后是冒泡监听器。​
4.
事件开始上浮: 完成目标阶段后,事件开始冒泡,从 child 上浮到 parent,触发了 parent 的冒泡监听器。​
5.
继续上浮: 事件继续上浮到 grandparent,触发了它的冒泡监听器,旅程结束。​
​
通过这个简单的实验,事件流的完整“V”字形路径被清晰地展现在我们面前。理解这个模型是掌握事件委托、阻止事件传播等高级技巧的基础。​
​