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

JavaScript的事件传播机制

你在学习和编写JavaScript时可能听说过事件冒泡(event bubbling)。它会发生在多个元素存在嵌套关系,并且这些元素都注册了同一事件(例如click)的监听器时。

但是事件冒泡只是事件机制的一部分。它经常与事件捕获(event capturing)和事件传播(event propagation)一起被提及。对于在JavaScript中处理事件来说,对这三个概念的透彻理解是非常必要的——例如,你希望实现事件委托模式。

什么是事件传播?

让我们从事件传播开始。这是事件冒泡和事件捕获的统称。以一个相册缩略图列表为例:
在这里插入图片描述
点击一张图片后不仅会为对应的 img 元素生成一个 click 事件,还会为它的父级 a 元素以及祖父级 li元素等上级元素生成一个 click 事件,一直到达该元素的最顶级上级元素,最后在 window 对象上终止。

用DOM术语来说,该图片是事件目标(event target),是最内层的元素,点击就是在这个元素上产生的。事件目标加上它的所有上级元素,从它的父级元素一直到window对象,在DOM树中形成了一个分支。例如,对于我们的例子来说,这个分支将由如下节点组成: img、a、li、ul、body、html、document、window。

注意window实际上并不是DOM节点,不过它实现了 EventTarget 接口,所以为了简便起见,我们为把它视为 document 对象的父级元素来处理。

这个分支很重要,因为它是事件传播的路径。这种传播是调用指定类型事件所有监听器的过程,这些监听器绑定在了这个分支上的节点上。每个监听器在调用时会有一个 event 对象,它含有关于当前事件的信息(稍后详细介绍)。

记得在一个节点上,可以为相同的事件类型注册多个监听器。当事件传播到达此节点时,监听器按照它们注册的顺序被调用。

事件传播是双向的,从window到事件目标,然后再返回。这种传播可以分为三个阶段:

  • 从window到事件目标的父级元素:这是捕获阶段
  • 事件目标自身:这是目标阶段
  • 从事件目标的父级元素回到 window:这是冒泡阶段

事件捕获阶段

在这一阶段,只有那些设置为捕获阶段工作的监听器才被调用。要为捕获阶段设置监听器,可以在调用 addEventListener 时设置第三个参数为 true:

在这里插入图片描述
如果省略此参数,则其默认值为false,该监听器在捕获阶段不工作,而是在冒泡阶段工作。

因此,在这个阶段,只有在从window到事件目标父级元素之间路径上找到的监听器才被调用。

事件目标阶段

在此阶段,将调用在事件目标上注册的所有监听器,而不管其捕获标志的值如何。

事件冒泡阶段

在事件冒泡阶段只有标记为非捕获的监听器才会被调用。也就是那些调用 addEventListener() 时第三个参数为 false 时注册的监听器。默认值即为false。

在这里插入图片描述
请注意,虽然所有事件都会在捕获阶段到达事件目标,不过有些事件,如focus、blur、load等,它们不会冒泡。也就是说,它们的事件传播在目标阶段后终止。

因此,在传播结束时,分支上的每个监听器都只被调用一次。

并非每种类型的事件都会冒泡。在传播过程中,监听器可以读取 event 对象的 .bubbles 属性来得知该事件是否冒泡。

W3C UIEvents规范的提供的如下图片演示了事件流的三个阶段。

在这里插入图片描述
访问事件传播信息

上面我提到了event对象的.bubbles属性。此对象提供了许多其他属性,可供监听器访问与传播相关的信息。

e.target 指向事件目标。
e.currentTarget 是正在执行的监听器注册到的节点。
我们可以用 e.eventPhase 得知当前的阶段。它的值是一个数字,1到3分别对应的是 Event 构造函数的常量 CAPTURING_PHASE, AT_TARGET 和 BUBBLING_PHASE。

整合在一起

我们把上面的概念付诸实践。我们的HTML代码如下:

在这里插入图片描述
event.js 内容如下:

在这里插入图片描述
我们为每个元素在捕获阶段和冒泡阶段都分别绑定了监听器,然后在浏览器中鼠标点击图片,在控制台中输出如下:

在这里插入图片描述
停止事件传播

事件传播是可以终止的,只需要在任意监听器中调用 event 对象的 stopPropagation() 方法。这意味着传播路径中当前节点之后节点上的所有监听器不会被调用了。不过,绑定在当前目标上的其他剩余监听器仍将调用。

我们仍使用上面的例子,现在想在图片点击后停止冒泡的过程,可以修改图片的click监听器如下:

在这里插入图片描述
执行结果如下:
在这里插入图片描述
在上图中可以看到冒泡阶段的监听器没有触发。

立即停止传播

除了 stopPropagation,还有 stopImmediatePropagation。正如它的名字所表明的那样,会立即停止事件传播,甚至阻止当前节点上的其他监听器被调用。

假设我们想要事件传播到了图片时立即停止继续传播,可以修改上面的 hanlder1 函数,把 stopPropagation 替换为 stopImmediatePropagation。执行效果如下:
在这里插入图片描述
我们可以看到绑定在图片上的第二个监听器函数并没有执行,事件传播过程被立即终止了。

事件的取消

有些事件会在传播结束后执行一些默认的浏览器操作。例如,单击一个链接或单击表单提交按钮分别会使浏览器导航到新页面和提交表单。

通过在监听器中调用event对象的另一个方法 preventDefault(),可以避免浏览器执行默认的操作。

结语

在本文中我们学习了事件冒泡和事件捕获是如何在JavaScript中工作的。如果你有任何问题或意见,欢迎留言。

相关文章:

JavaScript的事件传播机制

你在学习和编写JavaScript时可能听说过事件冒泡(event bubbling)。它会发生在多个元素存在嵌套关系,并且这些元素都注册了同一事件(例如click)的监听器时。 但是事件冒泡只是事件机制的一部分。它经常与事件捕获(event capturing)和事件传播…...

队列的定义及基本操作实现(链式)

个人主页:【😊个人主页】 系列专栏:【❤️数据结构与算法】 学习名言:天子重英豪,文章教儿曹。万般皆下品,惟有读书高 系列文章目录 第一章 ❤️ 学前知识 第二章 ❤️ 单向链表 第三章 ❤️ 递归 文章目录…...

集成方法!

目录 关注降低variance,选择bias较小的基学习器 Bagging Stacking Random Forest 关注降低bias,选择variance较小的基学习器 Adaboost Boosting 关注降低variance,选择bias较小的基学习器 Bagging 给定m个样本的数据集,利用有放回的随机采样法,得…...

20年程序员生涯,读了200多本技术书,挑了几本精华好书分享给大家

不知不觉已经又走过了20个年头了,今年已经44了,虽然我已经退休在家,但一直都保持着读书的习惯,我每年平均要读10本技术书籍,保持不让自己的技术落伍。 这些年读的技术书不下200本,很多好书我都会保存在家&a…...

C++ 手写一个WebServer

文章目录 前言一、WebServer的原理刨析二、HTTP协议基础三、C++代码实战四、运行测试前言 本文由:我不会画饼呀 提供建议 大家如果有什么想看的文章(想了解的知识点),都可以在本专栏文章底部评论,或者私信我,在有能力的前提下,我都会尽量给大家写出来,供大家学习参考 …...

Elasticsearch 简介与安装

简介 Elasticsearch 是一个开源的搜索引擎,建立在一个全文搜索引擎库 Apache Lucene™ 基础之上。 Lucene 可以说是当下最先进、高性能、全功能的搜索引擎库—​无论是开源还是私有。 但是 Lucene 仅仅只是一个库。为了充分发挥其功能,你需要使用 Java…...

Qt5.12实战之QByteArray与字符指针及字符串转换

示例源码:#include <QCoreApplication> #include <QDebug> #include <QTextStream> static QTextStream cout (stdout,QIODevice::WriteOnly); #include <iostream> #include <QtGlobal> #include <QByteArray>void test() {qDebug() <…...

二、ElasticSearch基础语法

目录一、简单了解ik分词器(分词效果)1.standard(单字分词器&#xff0c;es默认分词器)2.ik_smart分词(粗粒度的拆分)3.ik_max_word分词器&#xff08;最细粒度拆分&#xff09;二、指定默认分词器1.为索引指定默认分词器三、ES操作数据1.概述2.创建索引3.查询索引4.删除索引5.添…...

Yolov8详解与实战

文章目录摘要模型详解C2F模块Losshead部分模型实战训练COCO数据集下载数据集COCO转yolo格式数据集&#xff08;适用V4&#xff0c;V5&#xff0c;V6&#xff0c;V7&#xff0c;V8&#xff09;配置yolov8环境训练测试训练自定义数据集Labelme数据集摘要 YOLOv8 是 ultralytics …...

多线程案例——阻塞队列

目录 一、阻塞队列 1. 生产者消费者模型 &#xff08;1&#xff09;解耦合 &#xff08;2&#xff09;“削峰填谷” 2. 标准库中的阻塞队列 3. 自己实现一个阻塞队列&#xff08;代码&#xff09; 4. 自己实现生产者消费者模型&#xff08;代码&#xff09; 一、阻塞队列…...

学习优秀博文(【国产MCU移植】手把手教你使用RT-Thread制作GD32系列BSP)有感 | 文末赠书5本

学习优秀博文&#xff08;【guo产MCU移植】手把手教你使用RT-Thread制作GD32系列BSP&#xff09;有感 一篇优秀的博文是什么样的&#xff1f;它有什么规律可循吗&#xff1f;优秀的guo产32位单片机处理器是否真的能成功替换掉stm32的垄断地位&#xff1f; 本文博主以亲身经历聊…...

写用例写的焦头烂额?看看摸鱼5年的老点工是怎么写的...

给你个需求&#xff0c;你要怎么转变成最终的用例&#xff1f; 直接把需求文档翻译一下就完事了。 老点工拿到需求后的标准操作&#xff1a; 第一步&#xff1a;解析需求 先解析需求-找出所有需求中的动词&#xff0c;再列出所有测试点。测试点过程不断发散&#xff0c;对于…...

基于深度学习的鸟类检测识别系统(含UI界面,Python代码)

摘要&#xff1a;鸟类识别是深度学习和机器视觉领域的一个热门应用&#xff0c;本文详细介绍基于YOLOv5的鸟类检测识别系统&#xff0c;在介绍算法原理的同时&#xff0c;给出Python的实现代码以及PyQt的UI界面。在界面中可以选择各种鸟类图片、视频以及开启摄像头进行检测识别…...

零基础搭建Tomcat集群(超详细)

&#x1f497;推荐阅读文章&#x1f497; &#x1f338;JavaSE系列&#x1f338;&#x1f449;1️⃣《JavaSE系列教程》&#x1f33a;MySQL系列&#x1f33a;&#x1f449;2️⃣《MySQL系列教程》&#x1f340;JavaWeb系列&#x1f340;&#x1f449;3️⃣《JavaWeb系列教程》…...

机器学习自学笔记——聚类

聚类的基本概念 聚类&#xff0c;顾名思义&#xff0c;就是将一个数据集中各个样本点聚集成不同的“类”。每个类中的样本点都有某些相似的特征。比如图书馆中&#xff0c;会把成百上千的书分成不同的类别&#xff1a;科普书、漫画书、科幻书等等&#xff0c;方便人们查找。每…...

注意下C语言整形提升

C语言整形提升 C语言整形提升是指在表达式中使用多种类型的数据时&#xff0c;编译器会自动将较小的类型转换为较大的类型&#xff0c;以便进行运算。在C语言中&#xff0c;整型提升规则如下&#xff1a; 如果表达式中存在short类型&#xff0c;则将其自动转换为int类型。 如…...

Go panic的学习

一、前言 我们的应用程序常常会出现异常&#xff0c;包括由运行时检测到的异常或者应用开发者自己抛出的异常。 异常在一些其他语言中&#xff0c;如c、java&#xff0c;被叫做Exception&#xff0c;主要由抛出异常和捕获异常两部分组成。异常在go语言中&#xff0c;叫做pani…...

讲解Linux中samba理论讲解及Linux共享访问

♥️作者&#xff1a;小刘在C站 ♥️个人主页&#xff1a;小刘主页 ♥️每天分享云计算网络运维课堂笔记&#xff0c;努力不一定有收获&#xff0c;但一定会有收获加油&#xff01;一起努力&#xff0c;共赴美好人生&#xff01; ♥️夕阳下&#xff0c;是最美的绽放&#xff0…...

【C++笔试强训】第三十二天

&#x1f387;C笔试强训 博客主页&#xff1a;一起去看日落吗分享博主的C刷题日常&#xff0c;大家一起学习博主的能力有限&#xff0c;出现错误希望大家不吝赐教分享给大家一句我很喜欢的话&#xff1a;夜色难免微凉&#xff0c;前方必有曙光 &#x1f31e;。 &#x1f4a6;&a…...

OpenAI GPT-4震撼发布:多模态大模型

OpenAI GPT-4震撼发布&#xff1a;多模态大模型发布要点GPT4的新功能GPT-4:我能玩梗图GPT4:理解图片GPT4:识别与解析图片内容怎样面对GPT4申请 GPT-4 API前言&#xff1a; &#x1f3e0;个人主页&#xff1a;以山河作礼。 &#x1f4dd;​&#x1f4dd;:本文章是帮助大家更加了…...

OpenClaw可视化监控:百川2-13B-4bits任务执行状态的实时仪表盘搭建

OpenClaw可视化监控&#xff1a;百川2-13B-4bits任务执行状态的实时仪表盘搭建 1. 为什么需要可视化监控&#xff1f; 去年冬天&#xff0c;我部署了一个基于OpenClaw的自动化写作助手&#xff0c;对接本地运行的百川2-13B-4bits模型。最初几周运行良好&#xff0c;直到某天早…...

Windows 11系统优化终极指南:一键清理预装软件与隐私保护

Windows 11系统优化终极指南&#xff1a;一键清理预装软件与隐私保护 【免费下载链接】Win11Debloat 一个简单的PowerShell脚本&#xff0c;用于从Windows中移除预装的无用软件&#xff0c;禁用遥测&#xff0c;从Windows搜索中移除Bing&#xff0c;以及执行各种其他更改以简化…...

Crossplane认证考试指南:备考资源与实战题解析

Crossplane认证考试指南&#xff1a;备考资源与实战题解析 【免费下载链接】crossplane Crossplane 是一个开源的资源抽象层&#xff0c;用于管理多云计算资源&#xff0c;支持混合云和多云环境。 * 资源抽象层、多云和混合云环境管理 * 有什么特点&#xff1a;支持多种云服务提…...

Word制表位全攻略:从菜鸟到高手,5分钟搞定专业文档排版

Word制表位全攻略&#xff1a;从菜鸟到高手&#xff0c;5分钟搞定专业文档排版 你是否曾经为了对齐文档中的文字而疯狂敲击空格键&#xff1f;或是花费大量时间调整表格边框却依然无法让数字完美对齐&#xff1f;这些困扰其实只需要掌握一个Word中的隐藏神器——制表位&#x…...

手把手教你用Python实现双足机器人ZMP预观控制(附开源代码)

用Python实现双足机器人ZMP预观控制的完整指南 1. ZMP理论基础与机器人动力学模型 零力矩点(ZMP)理论是现代双足机器人步态规划的核心概念&#xff0c;它定义了地面反作用力合力作用点的位置。当ZMP位于支撑多边形(由机器人足底接触点构成的凸多边形)内时&#xff0c;机器人能保…...

RK3568 Android12长按电源键无反应?三步搞定关机菜单恢复

RK3568 Android12电源键功能失效排查与深度修复指南 在RK3568平台上进行Android12系统定制时&#xff0c;电源键功能异常是开发者常遇到的典型问题。不同于简单的功能缺失&#xff0c;这背后涉及系统级行为配置、手势交互逻辑和硬件抽象层的多层级适配。本文将带您从现象溯源到…...

别再死磕EKF了!用ESKF搞定无人机姿态估计,避开‘大数吃小数’的坑

无人机姿态估计实战&#xff1a;用ESKF避开EKF的数值陷阱 四轴飞行器在高速翻滚时&#xff0c;IMU数据突然出现剧烈抖动——这是去年调试自主无人机时遇到的真实场景。当时使用传统EKF算法&#xff0c;姿态解算在极端机动下频繁发散&#xff0c;直到切换到误差状态卡尔曼滤波&a…...

P1122 最大子树和

题目描述 小明对数学饱有兴趣&#xff0c;并且是个勤奋好学的学生&#xff0c;总是在课后留在教室向老师请教一些问题。一天他早晨骑车去上课&#xff0c;路上见到一个老伯正在修剪花花草草&#xff0c;顿时想到了一个有关修剪花卉的问题。于是当日课后&#xff0c;小明就向老…...

照着用就行:全学科适配的降AIGC工具 千笔·专业降AI率智能体 VS PaperRed 一站式解决降重难题

随着AI技术的迅猛发展&#xff0c;学术写作中对AI生成内容的识别能力也在不断提升&#xff0c;许多学生和研究者发现&#xff0c;原本依赖AI辅助撰写的论文&#xff0c;如今在查重系统中频频被标记出高AIGC率&#xff0c;甚至影响最终成绩。这种现象不仅让许多人措手不及&#…...

Zephyr RTOS 线程实战:从信号量到消息队列,手把手教你搞定多任务通信

Zephyr RTOS线程通信实战&#xff1a;信号量与消息队列的深度应用指南 在嵌入式开发领域&#xff0c;多任务间的有效通信是构建可靠系统的关键所在。想象这样一个场景&#xff1a;你的物联网设备需要同时处理传感器数据采集、实时数据处理、无线通信传输等多个任务&#xff0c;…...