当前位置: 首页 > news >正文

前端开发中的事件冒泡

目录

一、前言

二、什么是事件冒泡

1. 生活化比喻

2. 官方定义

3.场景展现

三、阻止冒泡的三种方式

四、stopPropagation()方法

4.1定义

4.2 行为拆解

4.3代码说明

五、事件参数

5.1 设置第三个参数

5.2代码看阶段差异

六、总结


一、前言

        在 Web 前端开发中,事件冒泡(Event Bubbling)阻止事件冒泡(Stop Propagation) 是日常开发绕不开的核心概念。它们决定了当用户点击、输入、滚动时,浏览器的响应顺序与范围。理解它们,才能真正掌控页面交互的“流向”,避免莫名其妙的“点一次触发两次”或“组件点不动”的尴尬。

二、什么是事件冒泡

1. 生活化比喻

想象 HTML 是一栋“俄罗斯套娃”大厦:

<body>        <!-- 大厦外墙 --><div>       <!-- 楼层 --><button>  <!-- 房间里的按钮 -->点我</button></div>
</body>

当你点击 button 时,浏览器会认为:你不仅点了按钮,也间接点了 div,也间接点了 body。于是事件会从最里层的 button 开始,一路“冒泡”到最外层的 document,这就叫 事件冒泡

2. 官方定义

W3C 标准的事件流分为 3 个阶段:

  1. 捕获阶段(Capture Phase)—— 从 window 到目标元素

  2. 目标阶段(Target Phase)—— 到达目标元素本身

  3. 冒泡阶段(Bubbling Phase)—— 从目标元素回到 window

事件冒泡 指的就是第 3 阶段:事件从 事件源祖先元素 逐级触发。

3.场景展现

<div id="modal"><div id="content"><button id="close">×</button></div>
</div>

需求:点击 modal 背景关闭弹窗,但点击 content 区域不关闭。

modal.addEventListener('click', () => modal.style.display = 'none');
content.addEventListener('click', (e) => {/* 不阻止冒泡会怎样?先触发 content 的回调,然后事件冒泡到 modal,导致 modal 的回调也被执行,弹窗被关闭 —— 违背需求!*/
});

三、阻止冒泡的三种方式

方式语法副作用
stopPropagation()e.stopPropagation()仅阻止冒泡,阻止同一元素上的后续监听
stoplmmediatePropagation()e.stopImmediatePropagation()阻止冒泡  阻止同一元素上剩余监听
参数true在事件中添加第三个参数为true并不能真正阻止事件冒泡

四、stopPropagation()方法

以上面代码要求为例,阻止冒泡实现需求

content.addEventListener('click', (e) => {e.stopPropagation(); // 关键点:事件到此为止,不再向上
});

4.1定义

stopPropagation() 是 DOM 事件对象中最常用的方法之一,用来“截断”当前事件在捕获/冒泡阶段的继续传播

语法结构:event.stopPropagation()

  • 无参数

  • 无返回值

  • 作用:阻止当前事件进一步传播(即后续捕获/冒泡节点再也收不到该事件)。

  • 标准:W3C DOM Level 2 起全浏览器支持(IE9+)

4.2 行为拆解

  1. 同一元素其他监听函数无效(默认它们仍会执行)。

  2. 连当前元素剩余监听也干掉,可使用 event.stopImmediatePropagation()

  3. 不会阻止浏览器的默认行为(需要 event.preventDefault()

4.3代码说明

<!doctype html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><title>stopPropagation() 对比</title><style>.box{ width: 180px; display:inline-block; vertical-align:top;padding:20px; margin:20px; border:3px dashed #ff4d4f; }button{ padding:8px 15px; margin-top:10px; }pre{ background:#f5f5f5; padding:10px; height:120px; overflow:auto; }</style>
</head>
<body><h3>左右同时点击按钮,观察日志差异</h3><div class="box" id="box1">没 stopPropagation()<button id="btn1">点我</button><pre id="log1"></pre>
</div><div class="box" id="box2">有 stopPropagation()<button id="btn2">点我</button><pre id="log2"></pre>
</div><script>const $ = id => document.getElementById(id);const log = (box, msg) => box.textContent += msg + '\n';[$('box1'), $('btn1')].forEach(el => {el.addEventListener('click', () => log($('log1'), `${el.tagName} 触发`));});[$('box2'), $('btn2')].forEach(el => {el.addEventListener('click', () => log($('log2'), `${el.tagName} 触发`));});$('btn2').addEventListener('click', e => {log($('log2'), '--- 调用 e.stopPropagation() ---');e.stopPropagation();   });
</script>
</body>
</html>

点击盒子中的按钮发现:

  • 左侧点击按钮 → 盒子也触发(冒泡上去了)

  • 右侧点击按钮 → 盒子不再触发(被stopPropagation()截断)

五、事件参数

addEventListener 的第三个参数(useCapture)本身并不能“阻止”冒泡,它只是决定你把监听器注册在捕获阶段还是冒泡阶段;真正能让事件“停下来的”仍然是监听器里手动调用的是stopPropagation()

5.1 设置第三个参数

参数含义
false(默认)监听器放在冒泡阶段触发
true监听器放在捕获阶段触发

5.2代码看阶段差异

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<div id="a"><div id="b"><button id="c">click</button></div>
</div><script>
function log(phase){ return () => console.log(phase); }
const [a,b,c] = ['a','b','c'].map(id=>document.getElementById(id));/* 全部注册两次,分别放在捕获、冒泡 */
[a,b,c].forEach(el=>{el.addEventListener('click', log(el.id+'-捕获'), true);   // 捕获el.addEventListener('click', log(el.id+'-冒泡'), false);  // 冒泡
});
</script>
</body>
</html>

点击按钮后的控制台顺序:

a-捕获 ➜ b-捕获 ➜ c-捕获 ➜ c-冒泡 ➜ b-冒泡 ➜ a-冒泡

(目标阶段触发顺序:按注册先后,这里先注册捕获所以先打印“c-捕获”)

六、总结

addEventListener 的第三个参数只是“阶段开关”,不是“闸门”;
停或不停,全靠你在监听函数里手动拉闸 —— stopPropagation()

阻止事件冒泡还是得使用stopPropagation()方式

http://www.dtcms.com/a/415225.html

相关文章:

  • 《Rust 程序设计语言》第二十一章:期末项目:构建多线程 Web 服务器
  • 作品 上海高端网站设计wordpress logo 编辑
  • day9.27
  • 做动画人设有哪些网站可以借鉴谷歌chrome浏览器下载
  • c++ 之多态虚函数表
  • 全屏网站 图片优化网站主机免费
  • 谷歌广告联盟网站同一个网站绑定多个域名
  • Java 大视界 -- Java 大数据机器学习模型在金融产品创新与客户需求匹配中的实战应用(417)
  • 美团网站是用什么做的网站开发企业开发
  • C语言风格哈希表vs C++风格哈希表的区别
  • 做数据分析网站做网站与数据库的关系
  • 六节tslib移植 、Qt移植到嵌入式linux
  • 做动漫图片的网站seo推广费用
  • 设计模式与原则精要
  • asp网站怎么做301定向系统商店
  • 大连html5网站建设价格泉州快速建站模板
  • LeetCode:64.搜索二维矩阵
  • 特殊矩阵的压缩存储
  • Qwen3-Omni多模态prompt输入解析
  • CVPR-2025 | 具身导航指令高效生成!MAPInstructor:基于场景图的导航指令生成Prompt调整策略
  • PRP (Product Requirement Prompts) - AI辅助开发提示词库
  • 昆明网站seo多少钱金舵设计园在线设计平台
  • AI识图 + MinIO图床 + 钉钉推送:打造全自动水质监测系统
  • EIGRP
  • 旅游电子商务网站开发方案网站运营数据周报表怎么做
  • 计算机视觉:人脸关键点定位与轮廓绘制
  • 手机网站建设基本流程专业的集团网站开发开发
  • Spring AI Alibaba:Java生态下的智能体开发全栈解决方案
  • 这么做网站网站三合一
  • Kurt-Blender零基础教程:第3章:材质篇——第3节:给模型上材质