查看: 121|回复: 1

JavaScript事件捕获与冒泡详解:事件流三阶段及stopPropagation实战

[复制链接]
发表于 2 小时前 | 显示全部楼层 |阅读模式
在浏览器中,点击一个按钮时,事件并不是瞬间只发生在按钮上,而是经历一次从顶层到目标、再从目标回顶层的完整传播过程,这就是DOM事件流。理解事件流是掌握JavaScript交互开发的基础。

事件流的三阶段
W3C标准将事件流分为三个阶段:
1. 捕获阶段(Capturing Phase):从window/document向下传播到目标元素的父元素,事件在此“寻找”目标。默认监听器不会在此阶段触发,除非明确指定。
2. 目标阶段(Target Phase):事件到达实际触发的元素,即event.target。
3. 冒泡阶段(Bubbling Phase):从目标元素向上传播回window,这是最常用的阶段,大多数事件监听器默认在此阶段触发。

代码实战:控制捕获与冒泡
使用addEventListener的第三个参数useCapture控制监听器在哪个阶段触发:true为捕获阶段,false(默认)为冒泡阶段。

示例HTML结构:
  1. <div id="grandparent">
  2.   爷爷
  3.   <div id="parent">
  4.     爸爸
  5.     <div id="child">儿子</div>
  6.   </div>
  7. </div>
复制代码

注册监听器:
  1. const grandparent = document.getElementById('grandparent');
  2. const parent = document.getElementById('parent');
  3. const child = document.getElementById('child');
  4. // 捕获阶段
  5. grandparent.addEventListener('click', () => console.log('Grandparent - Capture'), true);
  6. parent.addEventListener('click', () => console.log('Parent - Capture'), true);
  7. // 冒泡阶段
  8. parent.addEventListener('click', () => console.log('Parent - Bubble'));
  9. child.addEventListener('click', () => console.log('Child - Bubble'));
  10. // 点击child后控制台输出:
  11. // Grandparent - Capture
  12. // Parent - Capture
  13. // Child - Bubble
  14. // Parent - Bubble
复制代码

点击child时,捕获阶段先执行grandparent和parent的捕获监听器,然后到达目标child(冒泡监听器执行),最后向上冒泡到parent(冒泡监听器执行)。

阻止事件传播
使用event.stopPropagation()可阻止事件在DOM树中继续传播(同时阻止后续捕获和冒泡):
  1. child.addEventListener('click', function(event) {
  2.   event.stopPropagation();
  3.   console.log('Child clicked, stop!');
  4. });
复制代码

使用event.stopImmediatePropagation()则不仅阻止传播,还阻止当前元素上其他相同事件的监听器执行:
  1. child.addEventListener('click', function(event) {
  2.   event.stopImmediatePropagation();
  3.   console.log('Handler 1');
  4. });
  5. child.addEventListener('click', function() {
  6.   console.log('Handler 2');  // 不会执行
  7. });
复制代码

注意:在原生JavaScript中,return false不会阻止事件传播,必须显式调用stopPropagation或stopImmediatePropagation。

应用场景
1. 事件委托:利用冒泡,在父元素上统一监听子元素事件,提升性能。
  1. ul.addEventListener('click', function(event) {
  2.   if (event.target.tagName === 'LI') {
  3.     console.log('Clicked:', event.target.innerText);
  4.   }
  5. });
复制代码

2. 模态框关闭逻辑:点击遮罩层关闭弹窗,点击弹窗内部不关闭。
  1. overlay.addEventListener('click', () => closeModal());
  2. modal.addEventListener('click', (event) => event.stopPropagation());
复制代码

3. 高级拦截:在捕获阶段提前终止事件,实现全局权限检查或日志记录。
  1. document.addEventListener('click', function(event) {
  2.   if (event.target.disabled) {
  3.     event.stopPropagation();
  4.     event.preventDefault();
  5.   }
  6. }, true);
复制代码

掌握事件流三个阶段:先捕获,后目标,再冒泡;利用冒泡实现事件委托;使用stopPropagation控制事件传播范围。这是JS交互开发的必备技能。
回复

使用道具 举报

发表于 1 小时前 | 显示全部楼层

Re: JavaScript事件捕获与冒泡详解:事件流三阶段及stopPropagation实战

非常感谢楼主的详细讲解,把事件流的三个阶段、stopPropagation和stopImmediatePropagation的区别都说得非常清楚。尤其是那个“爷爷、爸爸、儿子”的例子,一下子就把捕获和冒泡的执行顺序讲明白了。之前我写事件委托时总担心会影响性能,现在理解了冒泡机制,用起来更有底气了。有个小问题想请教:如果同时在一个元素上绑定了捕获和冒泡监听器(比如parent),点击该元素自身时,两个监听器都会触发吗?还是只触发其中一个?期待楼主或各位坛友继续交流。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-6-11 17:01 , Processed in 0.027000 second(s), 17 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部