JavaScript中的事件冒泡、事件捕获、事件委托

news2024/12/24 3:08:13

DOM事件流(event flow )存在三个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段。

在这里插入图片描述
Dom标准事件流的触发的先后顺序为:先捕获再冒泡。即当触发dom事件时,会先进行事件捕获,捕获到事件源之后通过事件传播进行事件冒泡。
addEventListener的第三个参数
在我们平常用的addEventListener方法中,一般只会用到两个参数,一个是需要绑定的事件,另一个是触发事件后要执行的函数,然而addEventListener还可以传入第三个参数:

	element.addEventListener(event, function, useCapture);

第三个参数默认值是false,表示在事件冒泡阶段调用事件处理函数;如果参数为true,则表示在事件捕获阶段调用处理函数。如果不写第三个参数则默认在事件冒泡阶段调用事件处理函数。

下面先介绍事件冒泡:

事件冒泡

事件冒泡(dubbed bubbling):当一个元素接收到事件的时候,会把他接收到的事件传给自己的父级,一直到 window (注意这里传递的仅仅是事件,例如click、focus等等这些事件, 并不传递所绑定的事件函数。)
事件源 =>根节点(由内到外)进行事件传播。
举例说明:

在这里插入图片描述
给三个盒子依次绑定点击事件,当点击盒子的时候,会依次触发父级元素的点击事件。

	let big = document.querySelector('.big')
	let center = document.querySelector('.center')
	let small = document.querySelector('.small')
	big.addEventListener('click', () => {
	  console.log('big')
	})
	center.addEventListener('click', () => {
	  console.log('center')
	})
	small.addEventListener('click',()=>{
	  console.log('small')
	})

输出如下
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
如果父元素没有绑定点击事件则只会触发点击盒子的事件。

	let big = document.querySelector('.big')
	let center = document.querySelector('.center')
	let small = document.querySelector('.small')
	// big.addEventListener('click', () => {
	//   console.log('big')
	// })
	// center.addEventListener('click', () => {
	//   console.log('center')
	// })
	small.addEventListener('click', () => {
	  console.log('small')
	})

在这里插入图片描述
如果子元素(small)的点击事件去掉,当我们点击small的时候会把当前操作的点击事件传递给父元素(因为父元素绑定了点击函数)

	let big = document.querySelector('.big')
	let center = document.querySelector('.center')
	let small = document.querySelector('.small')
	big.addEventListener('click', () => {
	  console.log('big')
	})
	center.addEventListener('click', () => {
	  console.log('center')
	})
	// small.addEventListener('click', () => {
	//   console.log('small')
	// })

在这里插入图片描述
有些时候我们不希望产生事件冒泡,所以可以 在子事件中加入e.stopPropagation() 取消冒泡

	small.addEventListener('click', e => {
	  e.stopPropagation() // 阻止冒泡
	  console.log('small')
	})

这是时候再次点就,其他绑定了点击事件的父元素就不会再响应了
在这里插入图片描述

事件捕获

事件捕获(event capturing): 当鼠标点击或者触发dom事件时(被触发dom事件的这个元素被叫作事件源),浏览器会从根节点 =>事件源(由外到内)进行事件传播。
事件捕获与事件冒泡是比较类似的,最大的不同在于事件传播的方向。
还是举上面的例子:
tips; 因为事件冒泡是默认的,所以不做特殊处理

	let big = document.querySelector('.big')
	let center = document.querySelector('.center')
	let small = document.querySelector('.small')
	big.addEventListener('click', () => {
	  console.log('big-----事件捕获')
	}, true)
	center.addEventListener('click', () => {
	  console.log('center-----事件捕获')
	}, true)
	small.addEventListener('click', e => {
	  // e.stopPropagation() // 阻止冒泡
	  console.log('small-----事件捕获')
	}, true)
	big.addEventListener('click', () => {
	  console.log('big-----事件冒泡')
	})
	center.addEventListener('click', () => {
	  console.log('center-----事件冒泡')
	})
	small.addEventListener('click', e => {
	  // e.stopPropagation() // 阻止冒泡
	  console.log('small-----事件冒泡')
	},)

输出如下
在这里插入图片描述

事件委托

事件委托也称为事件代理。就是利用事件冒泡,把子元素的事件都绑定到父元素上。如果子元素阻止了事件冒泡,那么委托就无法实现。

不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点。

应用场景:1000个button需要注册点击事件

如果循环给每个按钮添加点击事件,那么会增加内存损耗,影响性能

	let btns = document.getElementsByTagName('button');
	console.log(btns);
	for (let i = 0; i < btns.length; i++) {
	  btns[i].addEventListener('click', function () {
	    console.log(i);
	  })
	}

此时可以给button的父元素添加点击事件

let btnFather = document.getElementById('btnfather');
btnFather.addEventListener('click', function () {
  console.log(e.target.innerHTML)
}

这时相当于每个按钮都绑定了点击事件

优点:

  1. 替代循环绑定事件的操作,减少内存消耗,提高性能。比如:

     在table上代理所有td的click事件。
     在ul上代理所有li的click事件。
    
  2. 简化了dom节点更新时,相应事件的更新。比如:

     不用在新添加的li上绑定click事件。
     当删除某个li时,不用移解绑上面的click事件。
    

缺点:

  1. 事件委托基于冒泡,对于不冒泡的事件不支持。
  2. 层级过多,冒泡过程中,可能会被某层阻止掉。
  3. 理论上委托会导致浏览器频繁调用处理函数,虽然很可能不需要处理。所以建议就近委托,比如在table上代理td,而不是在document上代理td。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

应届裁员,天胡开局——谈谈我的前端一年经历

应届裁员&#xff0c;天胡开局——谈谈我的前端一年经历 许久没有更新了&#xff0c;最近一个月都在忙&#xff0c;没错&#xff0c;正如题目所说&#xff0c;裁员然后找工作… 这周刚重新上班&#xff0c;工作第二天&#xff0c;感慨良多&#xff0c;记录些什么吧。 去年十…

AWS实战(一)-创建S3 存储桶

1&#xff09;登录AWS账号&#xff0c;选择服务—>存储—>S3。 2&#xff09;查看存储桶列表 3&#xff09;点击"创建存储桶"创建bucket。 4&#xff09;设置跨域 点击编辑&#xff0c;修改跨域设置即可。

基于SSM+Vue的健身房管理系统

基于SSMVue的健身房管理系统的设计与实现~ 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringMyBatisSpringMVC工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 主页 课程信息 健身器材 管理员界面 用户界面 摘要 健身房管理系统是一种利用现…

Day40 Advanced Docking System使用方法

1.ads简介 Qt自带的铆接部件是QDockWidget&#xff0c;也被称为浮动窗口部件。QDockWidget可以用来创建可停靠的面板&#xff0c;它能够与QMainWindow、QDialog或任何具有centralWidget的QMainWindow派生类进行连接。QDockWidget提供了一个框架&#xff0c;允许用户将内容面板放…

Duplicate keys detected: ‘0‘. This may cause an update error

Duplicate keys detected: ‘0’. This may cause an update error.当遇到该节点内容更新时&#xff0c;会因为重复的key导致无法更新。 该错误&#xff0c;是因为同级节点下存在两个由0开始的key&#xff0c;当遇到该节点内容更新时&#xff0c;会因为重复的key导致无法更新。…

AD9371 AGC

AD9371 系列快速入口 AD9371ZCU102 移植到 ZCU106 &#xff1a; AD9371 官方例程构建及单音信号收发 ad9371_tx_jesd -->util_ad9371_xcvr接口映射&#xff1a; AD9371 官方例程之 tx_jesd 与 xcvr接口映射 AD9371 官方例程 时钟间的关系与生成 &#xff1a; AD9371 官方…

【springmvc框架一文搞定】

SpringMVC框架 1. 搭建springmvc测试项目1.1 创建maven项目1.2 导入依赖pom.xml1.3 将springmvc容器加载到tomcat中1.4 启动tomcat插件1.5 访问路径&#xff1a; 2. 剖析启动过程2.1 启动服务器初始化过程2.2 访问路径执行过程 3.spring-springmvc bean的管理3.1 因为功能不同&…

信号发生器为什么输出信号和配置参数对不上?

1.问题&#xff1a; 今天在调试时遇到信号发生器输出信号与我实际输入的参数不符的问题。 我原本打算输出一个中心点是2.5V然后上下偏移1.5V的信号。刚操作信号发生器的时候&#xff0c;调节到正弦波输出&#xff0c;参数部分&#xff0c;必须要输入High,Low电平。这个很不方…

苍穹外卖项目笔记(1)

前言 苍穹外卖项目笔记附代码&#xff0c;贴上 github 链接&#xff0c;持续更新中&#xff1a;GitHub - Echo0701/sky-take-out &#xff08;不知道为啥发不了项目压缩包&#xff0c;那就下次再试试吧........&#xff09; 1 软件开发整体介绍 1.1 软件开发流程 1.2 角色分…

NOIP 2017 宝藏----Java题解

目录 NOIP 2017 宝藏 题目描述 输入描述: 输出描述: 输入 输出 说明 输入 输出 说明 备注: 代码实现&#xff1a; NOIP 2017 宝藏 时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 262144K&#xff0c;其他语言524288K 64bit IO For…

基于入侵杂草算法优化概率神经网络PNN的分类预测 - 附代码

基于入侵杂草算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于入侵杂草算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于入侵杂草优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神…

No201.精选前端面试题,享受每天的挑战和学习

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…

JavaWeb——CSS3的使用

目录 1. CSS概述 2. CSS引入方式 3. CSS颜色显示 4. CSS选择器 4.1. 元素&#xff08;标签&#xff09;选择器 4.2. id选择器 4.3. 类选择器 4.4. 三者优先级 5. 盒子模型 1. CSS概述 CSS&#xff0c;全称为“Cascading Style Sheets”&#xff0c;中文译为“层叠样式…

pycharm pro v2023.2.4(Python编辑开发)

PyCharm2023是一款集成开发环境&#xff08;IDE&#xff09;&#xff0c;专门为Python编程语言设计。以下是PyCharm2023的一些主要功能和特点&#xff1a; 代码编辑器&#xff1a;PyCharm2023提供了一个功能强大的代码编辑器&#xff0c;支持语法高亮、自动补全、代码调试、版…

CleanMyMac4.14中文免费版mac系统管理软件

许多小伙伴使用Mac后都反馈电脑不如想象中的流畅&#xff0c;甚至有点卡顿的现象&#xff0c;原因可能是因为无用的应用占据了过多的内存&#xff0c;或者是系统盘垃圾过多&#xff0c;导致的电脑卡顿现象。 今天小编教给大家几招&#xff0c;让自己的Mac能够一键重生&#xf…

7个UI设计师都在看的高质量SVG图标素材网站分享!

之前已经给大家分享过一些图标资源及素材灵感网站&#xff0c;大家的反响是不错的&#xff0c;想着你们可能好需要来点新鲜的高质量SVG图标素材网站&#xff0c;直接就是一整套统一设计风格的图标库&#xff0c;来一个图标系列大合集&#xff0c;帮你更快更好的找到风格适配的图…

Java版B/S架构云his医院信息管理系统源码(springboot框架)

一、技术框架 ♦ 前端&#xff1a;AngularNginx ♦ 后台&#xff1a;JavaSpring&#xff0c;SpringBoot&#xff0c;SpringMVC&#xff0c;SpringSecurity&#xff0c;MyBatisPlus&#xff0c;等 ♦ 数据库&#xff1a;MySQL MyCat ♦ 缓存&#xff1a;RedisJ2Cache ♦ 消息队…

保序回归:拯救你的校准曲线(APP)

保序回归&#xff1a;拯救你的校准曲线&#xff08;APP&#xff09; 校准曲线之所以是评价模型效能的重要指标是因为&#xff0c;校准曲线衡量模型预测概率与实际发生概率之间的一致性&#xff0c;它可以帮助我们了解模型的预测结果是否可信。一个理想的模型应该能够准确地预测…

超实用的公众号排版保姆级教程,纯干货

公众号排版的重要性首先体现在能够提高阅读体验。一个好的排版可以让读者在阅读过程中感觉舒适、流畅&#xff0c;降低阅读压力。 公众号的排版风格也是品牌形象的一部分。一个专业的排版&#xff0c;不仅可以提高读者的信任度&#xff0c;也可以增强品牌的独特性。例如&#…

无需数据库服务器部署脚本,全能型开源数据库监控平台lepus

Lepus 是一款开源的数据库监控平台&#xff0c;目前已经支持 MySQL、Oracle、SQLserver、MongoDB、Redis 等数据库的基本监控和告警。 Lepus 在监控数据库时&#xff0c;无需在每台数据库服务器上部署脚本或 Agent&#xff0c;只需要在数据库中创建授权账号后&#xff0c;即可…