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

深入理解JavaScript的事件冒泡与事件捕获

前言

JavaScript中提供了很多操作DOM的API。

事件冒泡事件捕获是指浏览器中处理DOM元素上事件的两种不同方式。事件冒泡和事件捕获都是JavaScript事件模型中的一部分,可以用来处理事件

对于这个问题,在实际开发中,并不是非常重要,因为在工作中我们基本上不会直接操作DOM,为了高效一般都是通过Vue、React这些框架,所以关于事件处理程序的一些坑直接就被避免了!!!

但是,多了解一点是没有坏处的,毕竟面试会考~

一、事件冒泡

事件冒泡(Event Bubbling)是指当一个元素触发了某个事件时,该事件会从最具体的元素开始逐级向上传播到较为不具体的元素(也就是从子元素向父元素方向传播),直到传播到文档的根节点为止。这种传播方式就像气泡从水底冒出水面一样,所以叫做事件冒泡。

举个例子,假设有一个包含两个嵌套 div 元素的 HTML 结构如下:

<div id="outer"><div id="inner"><button>点击我</button></div>
</div>

当我们在按钮上点击时,事件会按照如下顺序进行冒泡

  1. 首先,按钮元素触发点击事件。

  1. 然后,该事件会从最具体的元素(按钮元素)开始向外传播到其父元素(内部 div 元素)。

  1. 接着,该事件继续向外传播到外部 div 元素。

  1. 最后,该事件传播到文档的根节点(HTML 元素)。

在这个过程中,每个元素都可以在自己的事件处理程序中处理该事件。这意味着,当点击按钮时,除了按钮本身的事件处理程序之外,内部 div 和外部 div 元素也可以捕获并处理该事件

可以通过 JavaScript 的 Event 对象来阻止事件冒泡。例如,可以使用 event.stopPropagation() 方法来阻止事件继续向外传播。

二、事件捕获

事件捕获(Event Capturing)是一种处理事件的方式,与事件冒泡相反。事件捕获从文档根节点开始,逐级向下传播到最具体的元素,也就是从父元素向子元素方向传播。

与事件冒泡不同,事件捕获在元素本身触发事件之前被触发。具体来说,事件会从文档根节点开始向下传播,直到达到触发该事件的最具体的元素。这个过程中,每个元素都可以在自己的事件处理程序中处理该事件。

还是刚才的例子

<div id="outer"><div id="inner"><button>点击我</button></div>
</div>

当我们在按钮上点击时,事件会按照如下顺序进行捕获:

  1. 首先,该事件从文档的根节点开始向下传播到最外层的元素(外部 div 元素)。

  1. 然后,该事件继续向下传播到内部的 div 元素。

  1. 最后,该事件传播到触发该事件的最具体的元素(按钮元素)。

在这个过程中,每个元素都可以在自己的事件处理程序中处理该事件。这意味着,当点击按钮时,除了按钮本身的事件处理程序之外,内部 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事件模型的优点:

  1. 支持事件捕获和事件冒泡。事件捕获和事件冒泡是DOM2事件模型的核心特性之一,使得事件处理程序能够在DOM树中不同的层级进行注册,从而更好地控制事件的传播和处理。

  1. 可以同时添加多个事件处理程序。通过addEventListener()方法,可以为同一个事件添加多个事件处理程序,而不会覆盖先前添加的事件处理程序。

  1. 可以从HTML元素上删除事件处理程序。使用removeEventListener()方法可以方便地从HTML元素上删除事件处理程序,而不必像DOM0事件模型那样通过将事件处理程序设置为null来达到删除的效果。

  1. 支持事件对象。在DOM2事件模型中,事件处理程序会接收一个事件对象作为参数,该事件对象包含有关事件的详细信息,例如事件类型、事件目标、鼠标位置等,从而能够更好地处理和控制事件。

综上所述,DOM2事件模型是一种功能更强大、更灵活的事件模型,相比于DOM0事件模型和IE事件模型更加推荐使用。

四、两者能干什么?

使用事件冒泡和事件捕获可以实现:

  1. 事件委托:可以将事件处理程序绑定到父元素而不是子元素上。当子元素触发该事件时,事件将沿着冒泡路径传递到父元素,由父元素的事件处理程序进行处理。这样可以减少事件处理程序的数量,提高性能和可维护性。

  1. 事件拦截:通过在事件处理程序中调用 event.stopPropagation() 方法,可以阻止事件继续传播,从而避免不必要的事件触发和处理。

  1. 多个事件处理程序的执行顺序控制:通过在捕获或冒泡阶段注册事件处理程序,并控制其在事件传播路径上的位置,可以控制多个事件处理程序的执行顺序。

总之,了解和使用事件冒泡和事件捕获可以帮助我们更好地处理 HTML 和 JavaScript 中的事件,提高代码的可维护性和性能。

相关文章:

深入理解JavaScript的事件冒泡与事件捕获

前言JavaScript中提供了很多操作DOM的API。事件冒泡和事件捕获是指浏览器中处理DOM元素上事件的两种不同方式。事件冒泡和事件捕获都是JavaScript事件模型中的一部分&#xff0c;可以用来处理事件。对于这个问题&#xff0c;在实际开发中&#xff0c;并不是非常重要&#xff0c…...

格密码学习笔记(六):格中模运算

文章目录格中取模运算CVP和格的陪集致谢格中取模运算 定义&#xff08;格的基本区域&#xff09; 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++】非常重要的——多态

凡是面向对象的语言&#xff0c;都有三大特性&#xff0c;继承&#xff0c;封装和多态&#xff0c;但并不是只有这三个特性&#xff0c;是因为者三个特性是最重要的特性&#xff0c;那今天我们一起来看多态&#xff01; 目录 1.多态的概念 1.1虚函数 1.2虚函数的重写 1.3虚…...

发票账单很多?python助你批量完成数据提取

每天面对成堆的发票&#xff0c;无论是税务发票还是承兑单据&#xff0c;抑或是其他各类公司数据要从照片、PDF等不同格式的内容中提取&#xff0c;我们都有必要进行快速办公的能力提升。因此&#xff0c;我们的目标要求就十分明显了&#xff0c;首先要从图片中获取数据&#x…...

[闪存2.1] NAND FLASH特性串烧 | 不了解闪存特性,你能用好闪存产品吗?

前言 为了利用好闪存, 发挥闪存的优势, 以达到更好的性能和使用寿命, 那自然要求了解闪存特性。 闪存作为一种相对较新的存储介质, 有很多特别的特性。 一.闪存的特性 凡是采用Flash Memory的存储设备,可以统称为闪存存储。我们经常谈的固态硬盘(SSD),可以由volatile/…...

面试官问我按钮级别权限怎么控制,我说v-if,面试官说再见

最近的面试中有一个面试官问我按钮级别的权限怎么控制&#xff0c;我说直接v-if啊&#xff0c;他说不够好&#xff0c;我说我们项目中按钮级别的权限控制情况不多&#xff0c;所以v-if就够了&#xff0c;他说不够通用&#xff0c;最后他对我的评价是做过很多东西&#xff0c;但…...

阿里云服务器使用教程:CentOS 7安装nginx详细步骤

目录 1、下载nginx压缩包 2、配置nginx安装所需环境 3、解压nginx压缩包 4、编译安装nginx 5、nginx启动...

Android JNI浅析、Java和Native通信对象的传值和回调

简单了解一下jni JNI是一个本地编程接口&#xff0c;它允许运行在Java虚拟机的Java代码与用其他语言&#xff08;如C,C和汇编&#xff09;编写的库交互。 jni函数签名 首先看一下java类型对应的jni类型&#xff1a; Java类型符号BooleanZByteBCharCShortSIntILongJFloatFDo…...

linux目录/usr/lib/systemd/system目录详解

文章目录前言一. systemd介绍二. service 脚本详解2.1 [Unit] 区块2.2 [Service] 区块2.3 [Install] 区块总结前言 init的进化经历了这么几个阶段&#xff1a; CentOS 5: SysV init,串行 CentOS 6&#xff1a;Upstart,并行&#xff0c;借鉴ubuntu CentOS 7&#xff1a;Syste…...

408考研计算机之计算机组成与设计——知识点及其做题经验篇目4:CPU的功能和基本结构

随着考研的慢慢复习&#xff0c;我们逐渐进入了计算机组成与设计的第五章中央处理器。它原名为CPU。姓C&#xff0c;名PU&#xff0c;字中央处理器&#xff0c;号计组难点&#xff0c;乃计算机之中心与核心部件&#xff0c;小编称之曰能算能控&#xff0c;赐名曰九天宏教普济生…...

2022-12-10青少年软件编程(C语言)等级考试试卷(五级)解析

2022-12-10青少年软件编程(C语言)等级考试试卷(五级)解析T1、漫漫回国路 2020年5月,国际航班机票难求。一位在美国华盛顿的中国留学生,因为一些原因必须在本周内回到北京。现在已知各个机场之间的航班情况,求问他回不回得来(不考虑转机次数和机票价格)。 时间限制:10…...

刷题专练之链表(一)

文章目录前言一、 移除链表元素1.题目介绍2.思路3.代码二、反转链表1.题目介绍2.思路3.代码三、链表的中间结点1.题目介绍2.思路3.代码四、链表的中间结点1.题目介绍2.思路3.代码前言 以下是链表经常考的面试题&#xff0c;我在这里进行归纳和讲解&#xff0c;采取的是循序渐进…...

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>使用编程的形式…...

力扣-股票的资本损益

大家好&#xff0c;我是空空star&#xff0c;本篇带大家了解一道简单的力扣sql练习题。 文章目录前言一、题目&#xff1a;1393. 股票的资本损益二、解题1.正确示范①提交SQL运行结果2.正确示范②提交SQL运行结果3.正确示范③提交SQL运行结果4.正确示范④提交SQL运行结果5.其他…...

蓝桥杯刷题冲刺 | 倒计时26天

作者&#xff1a;指针不指南吗 专栏&#xff1a;蓝桥杯倒计时冲刺 &#x1f43e;马上就要蓝桥杯了&#xff0c;最后的这几天尤为重要&#xff0c;不可懈怠哦&#x1f43e; 文章目录1.路径2.特别数的和3.MP3储存4.求和1.路径 题目 链接&#xff1a; 路径 - 蓝桥云课 (lanqiao.cn…...

嵌入式软件开发之Linux 用户权限管理

目录 Ubuntu 用户系统 权限管理 权限管理命令 权限修改命令 chmod 文件归属者修改命令 chown Ubuntu 用户系统 Ubuntu 是一个多用户系统&#xff0c;我们可以给不同的使用者创建不同的用户账号&#xff0c;每个用户使用各自的账号登陆&#xff0c;使用用户账号的目的一是方便…...

2023-03-15 RabbitMQ

RabbitMQ整合 官网erlang版本 : 20.3.8.x 官方rabbitMq版本&#xff1a; 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前序、中序以及后序遍历 学习二叉树结构&#xff0c;最简单的方式就是遍历。所…...

蓝桥杯刷题冲刺 | 倒计时28天

作者&#xff1a;指针不指南吗 专栏&#xff1a;蓝桥杯倒计时冲刺 &#x1f43e;马上就要蓝桥杯了&#xff0c;最后的这几天尤为重要&#xff0c;不可懈怠哦&#x1f43e; 文章目录1.卡片2.数字三角形3.购物单4.回文日期1.卡片 题目 链接&#xff1a; 卡片 - 蓝桥云课 (lanqiao…...

一文带你吃透操作系统

文章目录1. 进程、线程管理2. 内存管理3. 进程调度算法4. 磁盘调度算法5. 页面置换算法6. 网络系统7. 锁8. 操作系统知识点文章字数大约1.9万字&#xff0c;阅读大概需要65分钟&#xff0c;建议收藏后慢慢阅读&#xff01;&#xff01;&#xff01;1. 进程、线程管理 进程和线程…...

黑马Mybatis

Mybatis 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

STM32+rt-thread判断是否联网

一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

前端导出带有合并单元格的列表

// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例

文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

Spring Boot面试题精选汇总

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

C++ 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

c++第七天 继承与派生2

这一篇文章主要内容是 派生类构造函数与析构函数 在派生类中重写基类成员 以及多继承 第一部分&#xff1a;派生类构造函数与析构函数 当创建一个派生类对象时&#xff0c;基类成员是如何初始化的&#xff1f; 1.当派生类对象创建的时候&#xff0c;基类成员的初始化顺序 …...

elementUI点击浏览table所选行数据查看文档

项目场景&#xff1a; table按照要求特定的数据变成按钮可以点击 解决方案&#xff1a; <el-table-columnprop"mlname"label"名称"align"center"width"180"><template slot-scope"scope"><el-buttonv-if&qu…...

Python竞赛环境搭建全攻略

Python环境搭建竞赛技术文章大纲 竞赛背景与意义 竞赛的目的与价值Python在竞赛中的应用场景环境搭建对竞赛效率的影响 竞赛环境需求分析 常见竞赛类型&#xff08;算法、数据分析、机器学习等&#xff09;不同竞赛对Python版本及库的要求硬件与操作系统的兼容性问题 Pyth…...