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

DOM事件的传播机制

DOM事件的传播机制是指当一个事件在DOM树中触发时,它是如何在各个元素之间传播的。DOM事件传播机制分为三个阶段:捕获阶段、目标阶段和冒泡阶段。此外,还有一种常用的技术称为事件委托,它能够简化事件处理程序的绑定和管理。本文将详细介绍这些概念,并提供相应的代码示例。

事件与事件流

在介绍事件传播机制之前,我们先来了解一下什么是事件和事件流。在DOM中,事件是指用户与页面交互时发生的动作,比如点击、鼠标移动等。而事件流则是指这些事件在DOM树中传播的路径。

每次用户与一个网页进行交互,例如点击链接,按下一个按键或者移动鼠标时,就会触发一个事件。我们的程序可以检测这些事件,然后对此作出响应。从而形成一种交互。

这样可以使我们的页面变得更加的有意思,而不仅仅像以前一样只能进行浏览。

JavaScript 中采用一个叫做事件监听器的东西来监听事件是否发生。这个事件监听器类似于一个通知,当事件发生时,事件监听器会让我们知道,然后程序就可以做出相应的响应。

通过这种方式,就可以避免让程序不断地去检查事件是否发生,让程序在等待事件发生的同时,可以继续做其他的任务。

标准 DOM 事件流

DOM事件流是指在DOM树中,事件从最外层的节点开始传播,逐级向下,直到达到目标节点,然后再从目标节点向上传播到最外层的节点。

DOM事件流分为三个阶段:捕获阶段、目标阶段和冒泡阶段。

  1. 捕获阶段:事件从最外层的节点开始传播,逐级向下,直到达到目标节点。在捕获阶段中,事件会依次触发每个经过的节点上绑定的捕获型事件处理函数。
  2. 目标阶段:事件达到目标节点后,在目标节点上触发绑定的事件处理函数。在这个阶段中,只会触发目标节点上绑定的事件处理函数。
  3. 冒泡阶段:事件从目标节点开始向上传播,逐级向上,直到达到最外层的节点。在冒泡阶段中,事件会依次触发每个经过的节点上绑定的冒泡型事件处理函数。

在实际应用中,默认情况下大部分DOM事件都是按照冒泡方式进行传播。但是也可以通过调用addEventListener方法时传入第三个参数为true来将其设置为捕获方式进行传播。

总结起来,DOM事件流就是指从最外层的节点开始传播,逐级向下到达目标节点,然后再从目标节点向上传播到最外层的节点的过程。这个过程分为捕获阶段、目标阶段和冒泡阶段。

下面是一个示例,演示了标准 DOM 事件流的传播顺序:

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

 
const outer = document.getElementById('outer');
const inner = document.getElementById('inner');
const btn = document.getElementById('btn');outer.addEventListener('click', function() {console.log('外层元素被点击');
}, true);inner.addEventListener('click', function() {console.log('内层元素被点击');
}, true);btn.addEventListener('click', function() {console.log('按钮被点击');
});

当我们点击按钮时,控制台会输出以下内容:

外层元素被点击 内层元素被点击 按钮被点击

可以看到,事件首先在捕获阶段从外层元素开始传播,然后到达目标元素,最后在冒泡阶段从目标元素向上冒泡。

事件冒泡流

事件冒泡是指在DOM树中,事件从目标元素开始向上冒泡传播的过程。也就是说,在冒泡阶段,事件会依次触发父级元素的相同类型事件处理程序。

下面是一个示例,演示了事件冒泡的过程:

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

const outer = document.getElementById('outer');
const inner = document.getElementById('inner');
const btn = document.getElementById('btn');outer.addEventListener('click', function() {console.log('外层元素被点击');
});inner.addEventListener('click', function() {console.log('内层元素被点击');
});btn.addEventListener('click', function() {console.log('按钮被点击');
});

当我们点击按钮时,控制台会输出以下内容:

按钮被点击 内层元素被点击 外层元素被点击

可以看到,事件首先在目标元素上触发,然后在冒泡阶段依次触发父级元素的相同类型事件处理程序。

事件捕获流

事件捕获是指在DOM树中,事件从最外层的父级元素开始向下捕获传播的过程。也就是说,在捕获阶段,事件会依次触发父级元素的相同类型事件处理程序。

下面是一个示例,演示了事件捕获的过程:

 
<div id="outer"><div id="inner"><button id="btn">点击我</button></div>
</div>
const outer = document.getElementById('outer');
const inner = document.getElementById('inner');
const btn = document.getElementById('btn');outer.addEventListener('click', function() {console.log('外层元素被点击');
}, true);inner.addEventListener('click', function() {console.log('内层元素被点击');
}, true);btn.addEventListener('click', function() {console.log('按钮被点击');
});

当我们点击按钮时,控制台会输出以下内容:

外层元素被点击 内层元素被点击 按钮被点击

可以看到,事件首先在捕获阶段依次触发父级元素的相同类型事件处理程序,然后到达目标元素。

事件委托流

事件委托是一种常用的技术,它利用了事件冒泡的特性。通过在父级元素上绑定一个事件处理程序,可以监听子级元素触发的事件。这样一来,无论子级元素是已经存在的还是动态生成的,都可以通过父级元素来管理它们的事件。

下面是一个示例,演示了事件委托的过程:

 
<ul id="list"><li>列表项1</li><li>列表项2</li><li>列表项3</li>
</ul>

 
const list = document.getElementById('list');list.addEventListener('click', function(event) {if (event.target.tagName === 'LI') {console.log('列表项被点击');console.log('触发事件的目标元素是:', event.target);}
});

当我们点击任意一个列表项时,控制台会输出以下内容:

列表项被点击 触发事件的目标元素是: <li>列表项1</li>

可以看到,通过在父级元素上绑定点击事件处理程序,我们可以捕获到子级元素触发的点击事件,并且可以获取到触发事件的目标元素。这样一来,无论我们添加或删除列表项,只需要在父级元素上绑定一个事件处理程序即可。

总结

通过以上介绍,我们了解了DOM事件传播机制的三个阶段:捕获阶段、目标阶段和冒泡阶段。此外,我们还学习了如何利用事件委托来简化事件处理程序的绑定和管理。掌握这些概念和技巧,能够帮助我们更好地处理和管理DOM中的各种交互事件。

相关文章:

DOM事件的传播机制

DOM事件的传播机制是指当一个事件在DOM树中触发时&#xff0c;它是如何在各个元素之间传播的。DOM事件传播机制分为三个阶段&#xff1a;捕获阶段、目标阶段和冒泡阶段。此外&#xff0c;还有一种常用的技术称为事件委托&#xff0c;它能够简化事件处理程序的绑定和管理。本文将…...

gitlab利用CI多工程持续构建

搭建CI的过程中有多个工程的时候&#xff0c;一个完美的构建过程往往是子工程上的更新(push 或者是merge)触发父工程的构建&#xff0c;这就需要如下建立一个downstream pipeline 子仓库1 .gitlab-ci.yml stages:- buildbuild_job:stage: buildtrigger:project: test_user/tes…...

【C++初阶】四、类和对象(构造函数、析构函数、拷贝构造函数、赋值运算符重载函数)

相关代码gitee自取&#xff1a; C语言学习日记: 加油努力 (gitee.com) 接上期&#xff1a; 【C初阶】三、类和对象 &#xff08;面向过程、class类、类的访问限定符和封装、类的实例化、类对象模型、this指针&#xff09; -CSDN博客 引入&#xff1a;类的六个默认成员函数…...

js粒子效果(二)

效果: 代码: <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Particle Animation</title><…...

01.让自己习惯C++

让自己习惯C 条款1&#xff1a;视C为一个语言联邦 条款1中提到了将C看作为一个“语言联邦”的概念。具体来说&#xff0c;“语言联邦”是指将C看作由多种不同的子语言组成的联邦。每种子语言都有自己的惯用法、工具和库&#xff0c;可以用来解决特定的问题。因此&#xff0c;…...

ElementUI table+dialog实现一个简单的可编辑的表格

table组件如何实现可编辑呢&#xff1f; 我的需求是把table组件那样的表格&#xff0c;实现它点击可以弹出一个框&#xff0c;然后在这个框里面输入你的东西&#xff0c;然后将他回显回去&#xff0c;当然&#xff0c;输入的有可能是时间啥的。 为什么要弹出弹层不在框上直接…...

Rust语言精讲:数据类型全解析

大家好&#xff01;我是lincyang。 今天&#xff0c;我们将深入探讨Rust语言中的数据类型&#xff0c;这是理解和掌握Rust的基础。 Rust语言数据类型概览 Rust是静态类型语言&#xff0c;所有变量类型在编译时确定。Rust的数据类型分为两类&#xff1a;标量类型和复合类型。…...

《数据结构、算法与应用C++语言描述》-代码实现散列表(线性探查与链式散列)

散列表 完整可编译运行代码&#xff1a;Github:Data-Structures-Algorithms-and-Applications/_22hash/ 定义 字典的另一种表示方法是散列&#xff08;hashing&#xff09;。它用一个散列函数&#xff08;也称哈希函数&#xff09;把字典的数对映射到一个散列表&#xff08…...

Hadoop学习笔记:运行wordcount对文件字符串进行统计案例

文/朱季谦 我最近使用四台Centos虚拟机搭建了一套分布式hadoop环境&#xff0c;简单模拟了线上上的hadoop真实分布式集群&#xff0c;主要用于业余学习大数据相关体系。 其中&#xff0c;一台服务器作为NameNode&#xff0c;一台作为Secondary NameNode&#xff0c;剩下两台当…...

python编写简单登录系统(密码混淆加密)

输入非123的数字会显示输入123选项&#xff0c;输入空格或者回车会报错&#xff0c;因为choice设置成int型先输入2个正常账户进去预防了用户名为空&#xff0c;密码为空或者小于3个&#xff0c;用户名已存在3种情况只有用户名和对应的密码都输入正确才能登录成功输入选项3退出代…...

UVA1025 城市里的间谍 A Spy in the Metro

UVA1025 城市里的间谍 A Spy in the Metro 题面翻译 题目大意 某城市地铁是一条直线&#xff0c;有 n n n&#xff08; 2 ≤ n ≤ 50 2\leq n\leq 50 2≤n≤50&#xff09;个车站&#xff0c;从左到右编号 1 … n 1\ldots n 1…n。有 M 1 M_1 M1​ 辆列车从第 1 1 1 站开…...

【科普知识】什么是步进电机?

德国百格拉公司于1973年发明了五相混合式步进电机及其驱动器&#xff0c;1993年又推出了性能更加优越的三相混合式步进电机。我国在80年代以前&#xff0c;一直是反应式步进电机占统治地位&#xff0c;混合式步进电机是80年代后期才开始发展。 步进电机是一种用电脉冲信号进行…...

AWS云服务器EC2实例实现ByConity快速部署

1. 前言 亚马逊是全球最大的在线零售商和云计算服务提供商。AWS云服务器在全球范围内都备受推崇&#xff0c;被众多业内人士誉为“云计算服务的行业标准”。在国内&#xff0c;亚马逊AWS也以其卓越的性能和服务满足了众多用户的需求&#xff0c;拥有着较高的市场份额和竞争力。…...

Docker的项目资源参考

Docker的项目资源包括以下内容&#xff1a; Docker官方网站&#xff1a;https://www.docker.com/ Docker Hub&#xff1a;https://hub.docker.com/ Docker文档&#xff1a;https://docs.docker.com/ Docker GitHub仓库&#xff1a;https://github.com/docker Docker官方博客…...

wsl-ubuntu 系统端口总被主机端口占用问题解决

wsl-ubuntu 系统端口总被主机端口占用问题解决 0. 问题描述1. 解决方法 0. 问题描述 wsl-ubuntu 子系统中的服务&#xff0c;总是启动失败&#xff0c;错误信息是端口被占用。 用一些命令查看&#xff0c;被占用的端口也没有用服务启动。 1. 解决方法 运行&#xff0c; ne…...

详解自动化之单元测试工具Junit

目录 1.注解 1.1 Test 1.2 BeforeEach 1.3 BeforeAll 1.4 AfterEach 1.5 AfterAll 2. 用例的执行顺序 通过 order() 注解来排序 3. 参数化 3.1 单参数 3.2 多参数 3.3 多参数(从第三方csv文件读取数据源) 3.4 动态参数ParameterizedTest MethodSource() 4. 测试…...

超声波雪深传感器冬季里的科技魔法

在冬季的某个清晨&#xff0c;当你打开大门&#xff0c;被厚厚的积雪覆盖的大地映入眼帘&#xff0c;你是否曾想过&#xff0c;这片雪地的深度是多少&#xff1f;它又如何影响着我们的生活和环境&#xff1f;今天&#xff0c;我们将为你揭开这个谜团&#xff0c;介绍一款神秘的…...

2023年【熔化焊接与热切割】免费试题及熔化焊接与热切割模拟考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 熔化焊接与热切割免费试题是安全生产模拟考试一点通生成的&#xff0c;熔化焊接与热切割证模拟考试题库是根据熔化焊接与热切割最新版教材汇编出熔化焊接与热切割仿真模拟考试。2023年【熔化焊接与热切割】免费试题及…...

【数据结构】—搜索二叉树(C++实现,超详细!)

&#x1f3ac;慕斯主页&#xff1a;修仙—别有洞天 ♈️今日夜电波&#xff1a;消えてしまいそうです—真夜中 1:15━━━━━━️&#x1f49f;──────── 4:18 &#x1f504; ◀️ ⏸ ▶️…...

机器人算法—ROS TF坐标变换

1.TF基本概念 &#xff08;1&#xff09;什么是TF&#xff1f; TF是Transformations Frames的缩写。在ROS中&#xff0c;是一个工具包&#xff0c;提供了坐标转换等方面的功能。 tf工具包&#xff0c;底层实现采用的是一种树状数据结构&#xff0c;根据时间缓冲并维护多个参考…...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)

引言&#xff1a;为什么 Eureka 依然是存量系统的核心&#xff1f; 尽管 Nacos 等新注册中心崛起&#xff0c;但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制&#xff0c;是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

C# 类和继承(抽象类)

抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

Android第十三次面试总结(四大 组件基础)

Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成&#xff0c;用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机&#xff1a; ​onCreate()​​ ​调用时机​&#xff1a;Activity 首次创建时调用。​…...

CSS设置元素的宽度根据其内容自动调整

width: fit-content 是 CSS 中的一个属性值&#xff0c;用于设置元素的宽度根据其内容自动调整&#xff0c;确保宽度刚好容纳内容而不会超出。 效果对比 默认情况&#xff08;width: auto&#xff09;&#xff1a; 块级元素&#xff08;如 <div>&#xff09;会占满父容器…...

JS设计模式(4):观察者模式

JS设计模式(4):观察者模式 一、引入 在开发中&#xff0c;我们经常会遇到这样的场景&#xff1a;一个对象的状态变化需要自动通知其他对象&#xff0c;比如&#xff1a; 电商平台中&#xff0c;商品库存变化时需要通知所有订阅该商品的用户&#xff1b;新闻网站中&#xff0…...

基于 TAPD 进行项目管理

起因 自己写了个小工具&#xff0c;仓库用的Github。之前在用markdown进行需求管理&#xff0c;现在随着功能的增加&#xff0c;感觉有点难以管理了&#xff0c;所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD&#xff0c;需要提供一个企业名新建一个项目&#…...

JVM 内存结构 详解

内存结构 运行时数据区&#xff1a; Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器&#xff1a; ​ 线程私有&#xff0c;程序控制流的指示器&#xff0c;分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 ​ 每个线程都有一个程序计数…...

【JavaSE】多线程基础学习笔记

多线程基础 -线程相关概念 程序&#xff08;Program&#xff09; 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序&#xff0c;比如我们使用QQ&#xff0c;就启动了一个进程&#xff0c;操作系统就会为该进程分配内存…...

uniapp 开发ios, xcode 提交app store connect 和 testflight内测

uniapp 中配置 配置manifest 文档&#xff1a;manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号&#xff1a;4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...