1.事件流:捕获与冒泡 来源:https://w0hog67yl81.feishu.cn/wiki/KUAIwk1PtiMvmmkoHDecqbCenFg 采集状态:已完成正文采集;每次约0.55屏连续滚动到文末,按block id和代码行号累积;代码行号连续。 1. 核心心智模型 当你在网页上点击一个元素时,这个“点击事件”并不仅仅发生在该元素上。它经历了一个完整的旅程,这个旅程被称为 DOM 事件流 (Event Flow)。 想象一下一个三层嵌套的盒子:div (外层) > p (中层) > span (内层)。当你点击最里面的 span 时: 1. 捕获阶段 (Capturing Phase): 浏览器会从最外层的祖先 window 开始,像一个“指挥官”下达命令一样,逐级向下“探查”,经过 document、、、div、p,最终到达你点击的目标 span。这个从外到内的过程就是捕获阶段。 2. 目标阶段 (Target Phase): 事件到达了它的最终目的地——你实际点击的 span 元素。事件在这里被触发。 3. 冒泡阶段 (Bubbling Phase): 事件完成任务后,开始“汇报工作”。它会从 span 开始,逐级向上“冒泡”,经过 p、div,一直到 window。这个从内到外的过程就是冒泡阶段。 一句话总结:事件先从外到内“潜入”(捕获),到达目标后,再从内到外“浮出”(冒泡)。 默认情况下,我们用 addEventListener 添加的监听器只在 冒泡阶段 执行。 2. 示例:在控制台直观展示事件流 让我们用代码来直观地看到这个完整的路径。 HTML 结构:
Grandparent
Parent
Child
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”字形路径被清晰地展现在我们面前。理解这个模型是掌握事件委托、阻止事件传播等高级技巧的基础。