什么是JS事件流

什么是JS事件流?

一:事件冒泡

<!DOCTYPE html>
<html lang="en">
<head>
  <title>事件冒泡例子</title>
</head>
<body>
  <div id="box">点击我</div>
</body>
</html>

上述的代码点击页面的div元素后,click事件会以如下顺序发生:

1.<div>
2.<body>
3.<html>
4.document

此事件流就是事件冒泡

图1所示:

事件冒泡

代码模拟事件冒泡

<!DOCTYPE html>
<html lang="en">
<head>
  <title>事件冒泡例子</title>
</head>
<body>
  <div id="box">点击我</div>
</body>
<script>
  const boxDiv = document.getElementById('box')
  const body = document.body
  const html = document.documentElement
  boxDiv.addEventListener('click', function(e) {
    console.log('boxDiv',this)
  })
  body.addEventListener('click', function(e) {
    console.log('body', this)
  })
  html.addEventListener('click', function(e) {
    console.log('html:', this)
  })
  document.addEventListener('click', function(e) {
    console.log('document:', this)
  })
</script>
</html>

打印结果如下:
在这里插入图片描述


二:事件捕获

点击页面的div元素后,click事件会以如下顺序发生:

1.document
2.<html>
3.<body>
4.<div>

此事件流就是事件捕获

图2所示:

事件捕获

其中:

触发事件为 到达目标,通常在事件处理时被认为是冒泡阶段的一部分。

也就是说捕获一般从document到html,再到body…(目标对象的父标签)就结束了。

代码模拟事件捕获

<!DOCTYPE html>
<html lang="en">
<head>
  <title>事件冒泡例子</title>
</head>
<body>
  <div id="box">点击我</div>
</body>
<script>
  const boxDiv = document.getElementById('box')
  const body = document.body
  const html = document.documentElement
  boxDiv.addEventListener('click', function(e) {
    console.log('boxDiv',this)
  }, true)
  body.addEventListener('click', function(e) {
    console.log('body', this)
  }, true)
  html.addEventListener('click', function(e) {
    console.log('html:', this)
  }, true)
  document.addEventListener('click', function(e) {
    console.log('document:', this)
  }, true)
</script>
</html>

打印结果如下:

在这里插入图片描述


三:事件处理程序一般有以下两种方式:

1. 事件处理程序的名字以"on",例如上述的点击也可以写成如下:
// 给div添加点击事件  
    const boxDiv = document.getElementById('box')
    boxDiv.onclick = function (e) {
    	console.log('boxDiv',this)
    }
// 移除div的点击事件
	boxDiv.onclick = null
2. Event是为事件处理程序的添加和移除定义了两个方法addEventListener()removeEventListener(),这两个方法接受三个参数:事件名事件处理函数布尔值(默认false),true表示在捕获阶段调用事件处理程序,false表示在冒泡阶段用事件处理程序。
// 给div添加点击事件   
const boxDiv = document.getElementById('box')
boxDiv.addEventListener('click', function(e) {
	console.log('boxDiv add click',this)
})
// 移除div的点击事件   
boxDiv.removeEventListener('click', function(e) { // 无效果
	console.log('boxDiv remove click',this) 
})

// 打印出
boxDiv add click <div id="box">​点击我​</div>

更换以下:

const boxDiv = document.getElementById('box')

const handler = function (e) {
    console.log('boxDiv handler')
}
boxDiv.addEventListener('click', handler, false)
setTimeout(() => {
    boxDiv.removeEventListener('click', handler, false)
    console.log('点击事件已销毁')
}, 3000);

通过以上代码可知,注意事项:addEventListener() 添加的匿名函数无法删除!!!

阻止捕获和冒泡阶段中当前事件的进一步传播可以使用**event.stopPropagation()**

 const boxDiv = document.getElementById('box')
 const body = document.body
 const html = document.documentElement
 boxDiv.addEventListener('click', function(e) {
     console.log('boxDiv add click',this)
     e.stopPropagation()
 })
body.addEventListener('click', function(e) {
    console.log('body', this)
})
html.addEventListener('click', function(e) {
    console.log('html:', this)
})
document.addEventListener('click', function(e) {
    console.log('document:', this)
})

四:事件委托

“过多事件处理程序“的解决方案是使用事件委托。事件委托是利用事件冒泡,可以只使用一个事件处理程序来管理一种类型的事件。

示例代码:

// 点击li打印li内的文本
<!DOCTYPE html>
<html lang="en">
<head>
  <title>事件委托的例子</title>
</head>
<body>
  <ul id="ul">
    <li>我是第1个li</li>
    <li>我是第2个li</li>
    <li>我是第3个li</li>
    <li>我是第4个li</li>
    <li>我是第5个li</li>
    <li>我是第6个li</li>
  </ul>
  <script>
    const ul = document.getElementById('ul')
    ul.onclick = function (e) {
      console.log(e.target.innerHTML)
    }
  </script>
</body>
</html>

五:总结

  • Events规范事件流分为3个阶段:事件获,到达目标,事件冒泡
  • 实际当中几乎不会使用事件捕获,都是使用事件冒泡
  • 阻止捕获和冒泡可以使用event.stopPropagation()。
  • addEventListener()添加的匿名函数无法删除,需定义类似一个handler同样的参数来用removeEventListener()移除。
  • 事件委托就是利用事件冒泡的机制

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/20468.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

利用暴力攻击破解登陆密码

长久以来&#xff0c;入侵远程计算机系统的工具和技术并没有发生翻天覆地的变化。例如&#xff0c;在许多情况下&#xff0c;普通用户只要知道了相关密码&#xff0c;就能立刻变身为管理员。虽然这些情形听起来不够曲折&#xff0c;但在大多数情况下&#xff0c;暴力攻击是通过…

css3 flex弹性布局详解

css3 flex弹性布局详解 一、flexbox弹性盒子 2009年&#xff0c;W3C 提出了一种新的方案----Flex 布局&#xff0c;可以简便、完整、响应式地实现各种页面布局。目前&#xff0c;它已经得到了所有浏览器的支持&#xff0c;这意味着&#xff0c;现在就能很安全地使用这项功能。…

【一起啃书】《机器学习》第五章 神经网络

文章目录 第五章 神经网络5.1 神经元模型5.2 感知机与多层网络5.3 误差逆传播算法5.4 全局最小与局部极小5.5 其他常见神经网络5.6 深度学习 第五章 神经网络 5.1 神经元模型 神经网络是由具有适应性简单单元组成的广泛并行互连的网络&#xff0c;它的组织能够模拟生物神经系统…

生产流程图怎么制作?思路提供

生产流程图是一种图表&#xff0c;用来展示生产流程中的各个环节及其顺序。这种图表可以帮助企业管理者更好地了解生产过程中的各个环节&#xff0c;从而更好地进行管理和优化。生产流程图通常包括各个生产环节的名称、所需时间、参与人员、设备和工具等信息。 在制作生产流程图…

七大软件架构设计原则详解

目录 1、概述 2、七大设计原则 2.1、开闭原则 2.2、里氏替换原则 2.3、依赖倒置原则 2.4、单一职责原则 2.5、接口隔离原则 2.6、迪米特法则 2.7、合成复用原则 3、最后 VC常用功能开发汇总&#xff08;专栏文章列表&#xff0c;欢迎订阅&#xff0c;持续更新...&…

基于jdk1.8的Java服务监控和性能调优

JVM的参数类型 X参数 非标准参数-Xint: 解释执行-Xcomp: 第一次使用就编译成本地代码-Xmixed: JVM自己来决定是否编译成本地代码 默认使用的是mixed mode 用的不多, 只需要做了解, 用的比较多的是XX参数 XX参数 非标准化参数相对不稳定主要用来JVM调优和Debug Boolean: …

【Vue3+TS项目】硅谷甄选day02--后台管理系统模板搭建/项目配置

1 项目初始化 一个项目要有统一的规范&#xff0c;需要使用eslintstylelintprettier来对我们的代码质量做检测和修复&#xff0c;需要使用husky来做commit拦截&#xff0c;需要使用commitlint来统一提交规范&#xff0c;需要使用preinstall来统一包管理工具。 1.1 环境准备 n…

阿里云u1服务器通用算力型CPU处理器性能测评

阿里云服务器u1通用算力型Universal实例高性价比&#xff0c;CPU采用Intel(R) Xeon(R) Platinum&#xff0c;主频是2.5 GHz&#xff0c;云服务器U1实例的基准vCPU算力与5代企业级实例持平&#xff0c;最高vCPU算力与6代企业级实例持平&#xff0c;提供2c-32c规格和1:1/2/4/8丰富…

elasticsearch结构化查询(一)

在上一篇中我们介绍了DSL相关的知识&#xff0c;接下来我们将会学习elasticsearch的结构化查询&#xff0c;同时也实践一下上一篇的DSL的查询用法 什么是结构化搜索? 从《Elasticsearch权威指南》上摘取部分解释如下: 结构化搜索是指查询包含内部结构的数据。日期&#xff0…

MATLAB 之 函数文件、特殊形式的函数和程序调试与优化

文章目录 一、函数文件1. 函数文件的基本结构2. 函数调用2.1 函数调用的格式2.2 函数的递归调用2.3 函数参数的可调性2.4 全局变量与局部变量 二、特殊形式的函数1. 子函数2. 内联函数3. 匿名函数 三、程序调试与优化1. 程序调试方法1.1 利用调试函数进行程序测试1.2 利用调试工…

MySQL数据库,JDBC连接数据库操作流程详细介绍

前言&#xff1a; 在学完 MySQL 和 Java 后&#xff0c;我们通常会尝试使用 Java编译器 连接 MySQL数据库&#xff0c;从而达到使用编译器来操作数据库的效果。连接的这个过程会用 JDBC 相关知识&#xff0c;因此我把 JDBC 包的下载及导入流程&#xff0c;以及 JDBC 的使用流程…

1.Buffer_Overflow-1.Basic_Jump

github上面的练习题 git clone https://github.com/Adamkadaban/LearnPwn 然后开始做 先进行 readelf 然后进行执行看看 是怎么回事 ./buf1发现就是一个输入和输出 我们checksec看看 发现stack 保护关闭 开启了NX保护 我们进入ida64看看反汇编 我习惯先看看字符串 SHITF…

C#异步编程之数据并行及任务并行

基于Parallel.ForEach的数据并行使用 1.数据非并行 var items new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; DateTime t1 DateTime.Now; foreach (var item in items) {Console.WriteLine("数据非并行输出:{0}", item); } 2.数据并行,只要使用Parallel.ForEach P…

Docker高频使用命令总结(镜像与容器命令)

目录 一.Docker常用命令总结 1.镜像命令管理 2.容器命令管理 二.Docker镜像操作命令 1.docker search&#xff1a;搜索镜像 2.docker pull&#xff1a;下载镜像 3.docker push&#xff1a;上传镜像 4.docker images&#xff1a;查看本地镜像 5.docker inspect &#x…

360+ChatGLM联手研发中国版“微软+OpenAI”

文章目录 前言360与智谱AI强强联合什么是智谱AI360智脑360GLM与360GPT大模型战略布局写在最后 前言 5月16日&#xff0c;三六零集团&#xff08;下称“360”&#xff09;与智谱AI宣布达成战略合作&#xff0c;双方共同研发的千亿级大模型“360GLM”已具备新一代认知智能通用模…

Springboot——事物管理

文章目录 事务管理一、 Spring事务管理1.1 事务回顾1.2 案例&#xff1a; 解散部门&#xff08;未开启事务&#xff09;1.3 事务管理注解Transactional1.4 事务管理日志开关1.5 rollbackFor 异常回滚属性1.6 propagation 事务传播行为1.7 解散部门并记录操作日志1.7.1 创建数据…

技术探秘:揭秘Bean Factory与FactoryBean的区别!

大家好&#xff0c;我是小米&#xff0c;一个热衷于技术分享的29岁小编。今天&#xff0c;我们来聊一聊在Spring框架中常用的两个概念&#xff1a;beanFactory和FactoryBean。它们虽然看似相似&#xff0c;但实际上有着不同的用途和作用。让我们一起来揭开它们的神秘面纱吧&…

离散数学_九章:关系(6)

&#x1fa90;9.6 偏序 1、⛺偏序关系和偏序集⛲偏序关系⛲偏序&#xff08;关系&#xff09;的例子 a. “大于或等于” 关系b. “整除” 关系c. “包含” 关系 &#x1f3ac;偏序集&#x1f3ac;可比性&#xff08;comparability&#xff09; " ≼ " 符号a. 可比 &a…

基于野火F407骄阳开发板的苹果采摘机器人机械臂的采摘轨迹与夹持器的采摘动作的设计(1)

基于野火F407骄阳开发板的苹果采摘机器人机械臂的采摘轨迹与夹持器的采摘动作的设计&#xff08;1&#xff09; 苹果采摘机器人1、采摘流程与硬件设计2、机械臂驱动以及采摘轨迹设计2.1、台达A2电机驱动实现2.2、机械臂寻找苹果巡逻轨迹 苹果采摘机器人 1、采摘流程与硬件设计…

C++/Qt 小知识记录3

工作中遇到的一些小问题&#xff0c;总结的小知识记录&#xff1a;C/Qt 小知识 QLineEdit限制输入大于0的正整数QLayout内清空已布局的WidgetWindows结束进程直接结束&#xff0c;子进程不响应结束事件正常结束&#xff0c;子进程响应结束事件 CMake关闭控制台Console实体与值对…