深入理解JavaScript的事件冒泡与事件捕获
前言
JavaScript中提供了很多操作DOM的API。
事件冒泡和事件捕获是指浏览器中处理DOM元素上事件的两种不同方式。事件冒泡和事件捕获都是JavaScript事件模型中的一部分,可以用来处理事件。
对于这个问题,在实际开发中,并不是非常重要,因为在工作中我们基本上不会直接操作DOM,为了高效一般都是通过Vue、React这些框架,所以关于事件处理程序的一些坑直接就被避免了!!!
但是,多了解一点是没有坏处的,毕竟面试会考~
一、事件冒泡
事件冒泡(Event Bubbling)是指当一个元素触发了某个事件时,该事件会从最具体的元素开始逐级向上传播到较为不具体的元素(也就是从子元素向父元素方向传播),直到传播到文档的根节点为止。这种传播方式就像气泡从水底冒出水面一样,所以叫做事件冒泡。

举个例子,假设有一个包含两个嵌套 div 元素的 HTML 结构如下:
<div id="outer"><div id="inner"><button>点击我</button></div>
</div>当我们在按钮上点击时,事件会按照如下顺序进行冒泡:
首先,按钮元素触发点击事件。
然后,该事件会从最具体的元素(按钮元素)开始向外传播到其父元素(内部 div 元素)。
接着,该事件继续向外传播到外部 div 元素。
最后,该事件传播到文档的根节点(HTML 元素)。
在这个过程中,每个元素都可以在自己的事件处理程序中处理该事件。这意味着,当点击按钮时,除了按钮本身的事件处理程序之外,内部 div 和外部 div 元素也可以捕获并处理该事件。
可以通过 JavaScript 的 Event 对象来阻止事件冒泡。例如,可以使用 event.stopPropagation() 方法来阻止事件继续向外传播。
二、事件捕获
事件捕获(Event Capturing)是一种处理事件的方式,与事件冒泡相反。事件捕获从文档根节点开始,逐级向下传播到最具体的元素,也就是从父元素向子元素方向传播。

与事件冒泡不同,事件捕获在元素本身触发事件之前被触发。具体来说,事件会从文档根节点开始向下传播,直到达到触发该事件的最具体的元素。这个过程中,每个元素都可以在自己的事件处理程序中处理该事件。
还是刚才的例子
<div id="outer"><div id="inner"><button>点击我</button></div>
</div>当我们在按钮上点击时,事件会按照如下顺序进行捕获:
首先,该事件从文档的根节点开始向下传播到最外层的元素(外部 div 元素)。
然后,该事件继续向下传播到内部的 div 元素。
最后,该事件传播到触发该事件的最具体的元素(按钮元素)。
在这个过程中,每个元素都可以在自己的事件处理程序中处理该事件。这意味着,当点击按钮时,除了按钮本身的事件处理程序之外,内部 div 和外部 div 元素也可以捕获并处理该事件。
可以通过 JavaScript 的 Event 对象来阻止事件捕获。例如,可以使用 event.preventDefault() 方法来阻止事件的默认行为,也可以使用 event.stopPropagation() 方法来阻止事件继续向下传播。
三、事件处理程序
事件处理程序指的是一段程序代码,它用于响应特定事件的发生。在计算机编程中,事件通常是指用户与程序交互的某个动作,例如点击鼠标、按下键盘键或者在窗口中拖拽对象等。事件处理程序可以是一个函数、方法或者一段程序代码片段,当特定事件发生时,它将被执行。
事件流和事件处理程序是密切相关的概念,事件流定义了事件在程序中的传播方式,而事件处理程序则是用于响应这些事件的程序代码。
JavaScript的事件流
大致可以分成3种:
DOM0事件流
DOM2事件流
IE事件流

DOM0 事件流
当一个事件发生时,它首先在捕获阶段被处理,然后在冒泡阶段被处理。捕获阶段是从根节点到目标节点的过程,冒泡阶段则是从目标节点到根节点的过程。在 DOM0 事件流中,只有在冒泡阶段才会处理事件处理程序。
DOM2 事件流
与 DOM0 事件流不同,DOM2 事件流允许在捕获阶段和冒泡阶段都可以处理事件处理程序。这种事件流的好处在于可以更灵活地控制事件处理的顺序。
IE 事件流
IE 事件流与 DOM2 事件流类似,但是在捕获阶段和冒泡阶段的顺序相反,即从目标元素到根元素的捕获阶段,然后是从根元素到目标元素的冒泡阶段。
DOM2 事件流相对于 DOM0 事件流和 IE 事件流更加灵活和可控,因此是更好的选择。不过,为了保证跨浏览器的兼容性,通常需要在事件处理程序中同时使用捕获和冒泡两个阶段。
DOM0、DOM2和IE事件有什么区别?
DOM0和DOM2是两个不同版本的DOM事件模型,而IE事件模型是一种与DOM事件模型不同的事件模型。
DOM0事件模型指的是最初的DOM事件模型,它是在1998年定义的。在DOM0事件模型中,事件处理程序直接被添加到HTML元素的属性中,例如:
<button onclick="alert('Hello world!')">Click me</button>在这个例子中,点击按钮时,将弹出一个警告框,因为事件处理程序直接在按钮元素的onclick属性中定义。
DOM2事件模型是一个更加现代的事件模型,它是在2000年定义的。在DOM2事件模型中,事件处理程序通过addEventListener()方法添加到HTML元素上,例如:
document.querySelector('button').addEventListener('click', function() {alert('Hello world!');
});在这个例子中,点击按钮时,将弹出一个警告框,因为事件处理程序通过addEventListener()方法添加到按钮元素上。
与DOM事件模型不同,IE事件模型使用attachEvent()方法将事件处理程序添加到HTML元素上,例如:
document.querySelector('button').attachEvent('onclick', function() {alert('Hello world!');
});在这个例子中,点击按钮时,将弹出一个警告框,因为事件处理程序通过attachEvent()方法添加到按钮元素上。
DOM0事件模型和IE事件模型的主要区别在于事件处理程序的添加方式,而DOM2事件模型引入了更多的功能,如事件捕获和事件冒泡,并且可以同时添加多个事件处理程序。
哪一种模型更好?
在现代Web开发中,推荐使用DOM2事件模型,因为它提供了更多的功能和灵活性,可以更好地控制和管理事件。以下是一些使用DOM2事件模型的优点:
支持事件捕获和事件冒泡。事件捕获和事件冒泡是DOM2事件模型的核心特性之一,使得事件处理程序能够在DOM树中不同的层级进行注册,从而更好地控制事件的传播和处理。
可以同时添加多个事件处理程序。通过addEventListener()方法,可以为同一个事件添加多个事件处理程序,而不会覆盖先前添加的事件处理程序。
可以从HTML元素上删除事件处理程序。使用removeEventListener()方法可以方便地从HTML元素上删除事件处理程序,而不必像DOM0事件模型那样通过将事件处理程序设置为null来达到删除的效果。
支持事件对象。在DOM2事件模型中,事件处理程序会接收一个事件对象作为参数,该事件对象包含有关事件的详细信息,例如事件类型、事件目标、鼠标位置等,从而能够更好地处理和控制事件。
综上所述,DOM2事件模型是一种功能更强大、更灵活的事件模型,相比于DOM0事件模型和IE事件模型更加推荐使用。
四、两者能干什么?
使用事件冒泡和事件捕获可以实现:
事件委托:可以将事件处理程序绑定到父元素而不是子元素上。当子元素触发该事件时,事件将沿着冒泡路径传递到父元素,由父元素的事件处理程序进行处理。这样可以减少事件处理程序的数量,提高性能和可维护性。
事件拦截:通过在事件处理程序中调用 event.stopPropagation() 方法,可以阻止事件继续传播,从而避免不必要的事件触发和处理。
多个事件处理程序的执行顺序控制:通过在捕获或冒泡阶段注册事件处理程序,并控制其在事件传播路径上的位置,可以控制多个事件处理程序的执行顺序。
总之,了解和使用事件冒泡和事件捕获可以帮助我们更好地处理 HTML 和 JavaScript 中的事件,提高代码的可维护性和性能。
相关文章:
深入理解JavaScript的事件冒泡与事件捕获
前言JavaScript中提供了很多操作DOM的API。事件冒泡和事件捕获是指浏览器中处理DOM元素上事件的两种不同方式。事件冒泡和事件捕获都是JavaScript事件模型中的一部分,可以用来处理事件。对于这个问题,在实际开发中,并不是非常重要,…...
格密码学习笔记(六):格中模运算
文章目录格中取模运算CVP和格的陪集致谢格中取模运算 定义(格的基本区域) P⊂Rn:{Px∣x∈L}\mathcal{P} \subset \mathbb{R}^n : \{ \mathcal{P} \bm{x} | \bm{x} \in \mathcal{L} \}P⊂Rn:{Px∣x∈L}是Rn\mathbb{R}^nRn的一种划分。 用P\mathcal{P}P对…...
【C++】非常重要的——多态
凡是面向对象的语言,都有三大特性,继承,封装和多态,但并不是只有这三个特性,是因为者三个特性是最重要的特性,那今天我们一起来看多态! 目录 1.多态的概念 1.1虚函数 1.2虚函数的重写 1.3虚…...
发票账单很多?python助你批量完成数据提取
每天面对成堆的发票,无论是税务发票还是承兑单据,抑或是其他各类公司数据要从照片、PDF等不同格式的内容中提取,我们都有必要进行快速办公的能力提升。因此,我们的目标要求就十分明显了,首先要从图片中获取数据&#x…...
[闪存2.1] NAND FLASH特性串烧 | 不了解闪存特性,你能用好闪存产品吗?
前言 为了利用好闪存, 发挥闪存的优势, 以达到更好的性能和使用寿命, 那自然要求了解闪存特性。 闪存作为一种相对较新的存储介质, 有很多特别的特性。 一.闪存的特性 凡是采用Flash Memory的存储设备,可以统称为闪存存储。我们经常谈的固态硬盘(SSD),可以由volatile/…...
面试官问我按钮级别权限怎么控制,我说v-if,面试官说再见
最近的面试中有一个面试官问我按钮级别的权限怎么控制,我说直接v-if啊,他说不够好,我说我们项目中按钮级别的权限控制情况不多,所以v-if就够了,他说不够通用,最后他对我的评价是做过很多东西,但…...
阿里云服务器使用教程:CentOS 7安装nginx详细步骤
目录 1、下载nginx压缩包 2、配置nginx安装所需环境 3、解压nginx压缩包 4、编译安装nginx 5、nginx启动...
Android JNI浅析、Java和Native通信对象的传值和回调
简单了解一下jni JNI是一个本地编程接口,它允许运行在Java虚拟机的Java代码与用其他语言(如C,C和汇编)编写的库交互。 jni函数签名 首先看一下java类型对应的jni类型: Java类型符号BooleanZByteBCharCShortSIntILongJFloatFDo…...
linux目录/usr/lib/systemd/system目录详解
文章目录前言一. systemd介绍二. service 脚本详解2.1 [Unit] 区块2.2 [Service] 区块2.3 [Install] 区块总结前言 init的进化经历了这么几个阶段: CentOS 5: SysV init,串行 CentOS 6:Upstart,并行,借鉴ubuntu CentOS 7:Syste…...
408考研计算机之计算机组成与设计——知识点及其做题经验篇目4:CPU的功能和基本结构
随着考研的慢慢复习,我们逐渐进入了计算机组成与设计的第五章中央处理器。它原名为CPU。姓C,名PU,字中央处理器,号计组难点,乃计算机之中心与核心部件,小编称之曰能算能控,赐名曰九天宏教普济生…...
2022-12-10青少年软件编程(C语言)等级考试试卷(五级)解析
2022-12-10青少年软件编程(C语言)等级考试试卷(五级)解析T1、漫漫回国路 2020年5月,国际航班机票难求。一位在美国华盛顿的中国留学生,因为一些原因必须在本周内回到北京。现在已知各个机场之间的航班情况,求问他回不回得来(不考虑转机次数和机票价格)。 时间限制:10…...
刷题专练之链表(一)
文章目录前言一、 移除链表元素1.题目介绍2.思路3.代码二、反转链表1.题目介绍2.思路3.代码三、链表的中间结点1.题目介绍2.思路3.代码四、链表的中间结点1.题目介绍2.思路3.代码前言 以下是链表经常考的面试题,我在这里进行归纳和讲解,采取的是循序渐进…...
elasticsearch高级查询api
yml配置 #es配置 spring:elasticsearch:rest:uris: 192.168.16.188:9200添加依赖 <dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId> </dependency>使用编程的形式…...
力扣-股票的资本损益
大家好,我是空空star,本篇带大家了解一道简单的力扣sql练习题。 文章目录前言一、题目:1393. 股票的资本损益二、解题1.正确示范①提交SQL运行结果2.正确示范②提交SQL运行结果3.正确示范③提交SQL运行结果4.正确示范④提交SQL运行结果5.其他…...
蓝桥杯刷题冲刺 | 倒计时26天
作者:指针不指南吗 专栏:蓝桥杯倒计时冲刺 🐾马上就要蓝桥杯了,最后的这几天尤为重要,不可懈怠哦🐾 文章目录1.路径2.特别数的和3.MP3储存4.求和1.路径 题目 链接: 路径 - 蓝桥云课 (lanqiao.cn…...
嵌入式软件开发之Linux 用户权限管理
目录 Ubuntu 用户系统 权限管理 权限管理命令 权限修改命令 chmod 文件归属者修改命令 chown Ubuntu 用户系统 Ubuntu 是一个多用户系统,我们可以给不同的使用者创建不同的用户账号,每个用户使用各自的账号登陆,使用用户账号的目的一是方便…...
2023-03-15 RabbitMQ
RabbitMQ整合 官网erlang版本 : 20.3.8.x 官方rabbitMq版本: rabbitmq-server-generic-unix-3.7.14.tar.xz 1.安装 1.1 安装erlang 1.安装环境 yum -y install make gcc gcc-c kernel-devel m4 ncurses-devel openssl-devel2.在/usr/local/下创建erlangapp文件…...
二叉树链式结构的实现
文章目录1.二叉树的遍历1.1前序、中序以及后序遍历1.2代码测试1.3层序遍历1.4二叉树遍历习题2.节点个数以及高度2.1二叉树节点个数2.2叶子节点个树2.3第k层节点个数2.4树的高度1.二叉树的遍历 1.1前序、中序以及后序遍历 学习二叉树结构,最简单的方式就是遍历。所…...
蓝桥杯刷题冲刺 | 倒计时28天
作者:指针不指南吗 专栏:蓝桥杯倒计时冲刺 🐾马上就要蓝桥杯了,最后的这几天尤为重要,不可懈怠哦🐾 文章目录1.卡片2.数字三角形3.购物单4.回文日期1.卡片 题目 链接: 卡片 - 蓝桥云课 (lanqiao…...
一文带你吃透操作系统
文章目录1. 进程、线程管理2. 内存管理3. 进程调度算法4. 磁盘调度算法5. 页面置换算法6. 网络系统7. 锁8. 操作系统知识点文章字数大约1.9万字,阅读大概需要65分钟,建议收藏后慢慢阅读!!!1. 进程、线程管理 进程和线程…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...
OkHttp 中实现断点续传 demo
在 OkHttp 中实现断点续传主要通过以下步骤完成,核心是利用 HTTP 协议的 Range 请求头指定下载范围: 实现原理 Range 请求头:向服务器请求文件的特定字节范围(如 Range: bytes1024-) 本地文件记录:保存已…...
Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...
学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...
MySQL账号权限管理指南:安全创建账户与精细授权技巧
在MySQL数据库管理中,合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号? 最小权限原则…...
【Java学习笔记】BigInteger 和 BigDecimal 类
BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...
嵌入式学习笔记DAY33(网络编程——TCP)
一、网络架构 C/S (client/server 客户端/服务器):由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序,负责提供用户界面和交互逻辑 ,接收用户输入,向服务器发送请求,并展示服务…...
Golang——6、指针和结构体
指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...
comfyui 工作流中 图生视频 如何增加视频的长度到5秒
comfyUI 工作流怎么可以生成更长的视频。除了硬件显存要求之外还有别的方法吗? 在ComfyUI中实现图生视频并延长到5秒,需要结合多个扩展和技巧。以下是完整解决方案: 核心工作流配置(24fps下5秒120帧) #mermaid-svg-yP…...
