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

js中和Vue中的事件委托(事件代理)的实现方法

目录

一、事件委托(事件代理)

1、事件委托的优点

2、事件委托的缺点

3、为什么要使用事件委托

4、事件委托实现原理

5、DOM事件流

6、事件委托的实现方法

1、vue写法

1.1、html代码

1.2、js代码

2、原生的写法其实也差不多:

2.1、html代码

2.2、js代码

二、阻止事件冒泡

三、取消默认事件

四、总结


一、事件委托(事件代理)

将原本需要绑定在子元素上的事件监听器委托在父元素上,让父元素充当事件监听的职务。

利用事件冒泡的特性,在父节点上响应事件,而不是在子节点上响应事件的技术。它能够改善性能,因为只需要在父元素上设置一次事件监听器,就可以管理同一类型的所有子元素的事件。

即事件从最深的节点开始,逐步向上传播。在事件冒泡过程中,父元素会捕获到子元素的事件,并进行分析。通过查看event对象的属性,可以确定是哪个子元素的事件,从而执行相应的处理逻辑。

使用事件委托能够避免对每个子元素单独设置事件监听器,降低了与DOM交互的次数,提高了页面的整体运行性能。同时,事件委托也具有更高的灵活性和可维护性,不需要操作大量的DOM元素。

在Vue中,可以利用v-on指令或@符号来绑定事件监听器,并在父元素上设置事件委托。例如,可以在父元素上设置一个click事件监听器,然后在子元素上绑定一个click事件,通过事件委托实现父元素对子元素事件的响应。


1、事件委托的优点
  • 节省内存(dom与js的关联),减少事件的注册
  • 增加子元素也无需再注册事件
2、事件委托的缺点

获取绑定的节点数据会相对麻烦一点

3、为什么要使用事件委托

在日常开发中,很经常我们会遇到个问题,就是在长列表数据较多的时候,而又需要对子元素注册一些事件(如onClick),就会造成比较大的内存开支,很耗费性能,也可能会造成页面卡顿等等;
所以可以通过在父元素上添加@click监听,而不是在子元素上注册事件;
如果数据量比较少,就可忽略不计;

此外,事件处理程序需要与 DOM 节点进行交互,访问 DOM 的次数越多,引起浏览器重绘和重排的次数也就越多,从而影响页面的性能。

4、事件委托实现原理

事件委托是利用事件的冒泡原理来实现的,大致可以分为三个步骤:

  1. 确定要添加事件元素的父级元素;
  2. 给父元素定义事件,监听子元素的冒泡事件;
  3. 使用 event.target 来定位触发事件冒泡的子元素。

5、DOM事件流

事件流描述的是从页面中接收事件的顺序。事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流。

比如:我们给页面中的一个div注册了单击事件,当你单击了div时,也就单击了body,单击了html,单击了document。


DOM 事件流会经历3个阶段:

  • 捕获阶段:事件从文档的根节点流向目标对象。

事件从最不精确的对象(document 对象)开始触发,然后到最精确(也可以在窗口级别捕获事件,不过必须由开发人员特别指定),与事件冒泡相反,事件会从最外层开始发生,直到最具体的元素。

  • 当前目标阶段:在目标对象上被触发。
  • 冒泡阶段:回溯到文档的根节点。

微软提出了名为事件冒泡的事件流。事件按照从最特定的事件目标到最不特定的事件目标(document对象)的顺序触发。

6、事件委托的实现方法

1、vue写法
1.1、html代码
<div id="app"><div id="event-agent" @click="eventAgent"><p v-for="(item, index) in list" :key="index" :data-name="item.name" :data-index="index">{{item.name}}</p></div>
</div>

> 获取节点参数 (data-index、data-name),则在 $event.target.dataset  { index: 'xxx', name: 'xxx' } 中取值

1.2、js代码
data() {return { list: [{ id: 1, name: 'kmj1'},{ id: 2, name: 'kmj2'},{ id: 3, name: 'kmj3'},{ id: 4, name: 'kmj4'}]   }
},
methods: { // 事件委托eventAgent(e) {const target = e.target; console.log(target )// 注意 e.target.nodeName 的元素名是大写的if (target  && target.nodeName === "P") {const dataset = target .dataset;console.log('$event.target.dataset : ' dataset ); // $event.target.dataset :  { name: 'xxx', index: 'xxx' }}}
}
2、原生的写法其实也差不多:
2.1、html代码
<div id="event-agent"><p :data-name="Item1" :data-index="0">Item 1</p><p :data-name="Item2" :data-index="1">Item 2</p><p :data-name="Item3" :data-index="2">Item 3</p><p :data-name="Item4" :data-index="3">Item 4</p><p :data-name="Item5" :data-index="4">Item 5</p><p :data-name="Item6" :data-index="5">Item 6</p>
</div>
2.2、js代码
document.getElementById( "event-agent").onclick = function(event){ // 兼容Ie的写法event = event || window.event;var  target = event.target || event.srcElement;  // 注意 e.target.nodeName 的元素名是大写的if (target  && target.nodeName === "P") {const dataset = target .dataset;console.log('$event.target.dataset : ' dataset ); // $event.target.dataset :  { name: 'xxx', index: 'xxx' }}
}; // 也可以用这种方式,其实都差不多的:
// 冒泡阶段处理程序  
document.getElementById( "event-agent").addEventListener( "click", (e) => {},   false);
// 捕获阶段处理程序
document.getElementById( "event-agent").addEventListener( "click", (e) => {},   true);


二、阻止事件冒泡

W3C的方法是e.stopPropagation(),IE则是使用e.cancelBubble = true。 stopPropagation是事件的一个方法,作用是阻止目标元素的事件冒泡,但是不会组织默认行为。


 

function stopBubble(e) { 
//如果提供了事件对象,则这是一个非IE浏览器 
if ( e && e.stopPropagation ) //因此它支持W3C的stopPropagation()方法 e.stopPropagation(); 
else //否则,我们需要使用IE的方式来取消事件冒泡 window.event.cancelBubble = true; 
}

三、取消默认事件

W3C的方法是e.preventDefault(),IE则是使用e.returnValue = false。 preventDefault()是事件对象(Event)的一个方法,作用是取消一个目标元素的默认行为。既然是默认行为,那么元素必须有默认行为才能被取消,如果元素本身就没有默认行为,调用自然就无效了。什么元素有默认行为呢?如链接\<a href="">,提交按钮<input type=”submit”>等,这些都有默认行为。


 

function preventDefault(e){if(e && e.preventDefault){e.preventDefault();}else{window.event.returnValue = false;}return false;
}


 


四、总结

要使用事件委托,需要保证事件能够发生冒泡,适合使用事件委托的事件有 click、mousedown、mouseup、keydown、keyup、keypress 等。需要注意的是,虽然 mouseover 和 mouseout 事件也会发生事件冒泡,但处理起来非常麻烦,所以不推荐在 mouseover 和 mouseout 事件中使用事件委托。

另外,对于不会发生事件冒泡的事件(例如 load、unload、abort、focus、blur 等),则无法使用事件委托。

相关文章:

js中和Vue中的事件委托(事件代理)的实现方法

目录 一、事件委托&#xff08;事件代理&#xff09; 1、事件委托的优点 2、事件委托的缺点 3、为什么要使用事件委托 4、事件委托实现原理 5、DOM事件流 6、事件委托的实现方法 1、vue写法 1.1、html代码 1.2、js代码 2、原生的写法其实也差不多&#xff1a; 2.1、…...

C++学习笔记——对象的指针

目录 一、对象的指针 二、减少对象的复制开销 三、应用案例 游戏引擎 图像处理库 数据库管理系统 航空航天软件 金融交易系统 四、代码的案例应用 一、对象的指针 是一种常用的技术&#xff0c;用于处理对象的动态分配和管理。使用对象的指针可以实现以下几个方面的功…...

QT5.14 实现ModbusTCP客户端 Demo

本文在QT5.14平台&#xff0c;基于QModbusClientTcp类&#xff0c;实现了客户端对单个寄存器的读写&#xff0c;用ModbusSlave做服务器做测试。 1.界面 (1)更改读按钮的名称为bt_Read (2)更改写按钮的名称为bt_Write 2.修改pro文件的第三行 greaterThan(QT_MAJOR_VERSION, 4)…...

c++析构函数

析构函数的简述 1. 析构函数和构造函数类似&#xff0c;是c规定当对象的生命周期结束时&#xff0c;默认你会调用析构函数。 2. 同理&#xff0c;当我们不写析构函数的时候&#xff0c;编译器会自动生成一个空实现的析构函数。 3. 析构函数只能编译器自己调用&#xff0c;我们…...

nodejs 服务端token 高效缓存验证

在前后端分离开发过程中,经常涉及权限验证的问题,一般都是采用由服务端根据前端传递的用户名和密码,验证成功后生成token,然后前端在访问服务端接口时,再附带token访问。 如果服务端高频次的解析token,进行内容验证,则会大大降低接口性能,而采用内存或者redis进行合法…...

C++内存管理机制(侯捷)笔记2

C内存管理机制&#xff08;侯捷&#xff09; 本文是学习笔记&#xff0c;仅供个人学习使用。如有侵权&#xff0c;请联系删除。 参考链接 Youtube: 侯捷-C内存管理机制 Github课程视频、PPT和源代码: https://github.com/ZachL1/Bilibili-plus 下面是第二讲allocator具体实…...

java基础之异常练习题

异常 1.Java 中所有的错误/异常都继承自 Throwable类&#xff1b;在该类的子类中&#xff0c; Error 类表示严重的底层错误&#xff0c; 对于这类错误一般处理的方式是 直接报告并终止程序 &#xff1b; Exception 类表示异常。 2.查阅API&#xff0c;完成以下填空&#xff1a;…...

智慧旅游景区解决方案:PPT全文49页,附下载

关键词&#xff1a;智慧景区建设&#xff0c;智慧旅游平台&#xff0c;智慧旅游运营检测系统项目&#xff0c;智慧文旅&#xff0c;智慧景区开发与管理&#xff0c;智慧景区建设核心&#xff0c;智慧景区开发与管理 一、智慧景区建设现状 1、基础设施建设&#xff1a;智慧景区…...

Demo: 给图片添加自定义水印并下载

给图片添加自定义水印并下载 <template><div class"wrap"><div class"optea"><div class"file-upload"><p>选择图片</p><el-button type"text" style"color: #c00;"><label f…...

黑马苍穹外卖学习Day5

文章目录 Redis学习Redis简介准备工作Redis常用数据类型介绍各数据类型的特点Redis常用命令字符串操作命令哈希操作命令列表操作命令集合操作命令有序集合操作命令通用操作命令 在Java中操作Redis导入Spring Data Redis坐标配置Redis数据源编写配置类&#xff0c;创建RedisTemp…...

【.NET Core】可为null类型详解

【.NET Core】可为null类型详解 文章目录 【.NET Core】可为null类型详解一、概述二、可为空的值类型2.1 声明和赋值2.2 检查可为空值类型2.3 基础类型与可为空的值类型互换2.4 可为空的值类型装箱和取消装箱2.5 如何确定可为空的值类型 三、可为 null 的引用类型 一、概述 nu…...

基于知识图谱的健康知识问答系统

基于知识图谱的健康知识问答系统 引言数据集与技术选型数据集技术选型 系统功能与实现数据导入与图数据库构建问答任务设计与实现1. 实体提取2. 用户意图识别 前端聊天界面与问答系统 结语 引言 随着互联网的发展&#xff0c;人们对健康知识的需求逐渐增加。为了更方便地获取健…...

橘子学K8S03之容器的理解

前面我们知道了容器是通过对一个普通的linux进程进行隔离和限制实现的一种特殊视角下的进程表现。而隔离和限制的实现技术分别是"Namespace"和“Cgroups”,在这两种机制的控制下&#xff0c;我们需要知道容器的本质是一种特殊的进程。 我们现在有了这个认知之后&…...

算法第十二天-矩形区域不超过K的最大数值和

矩形区域不超过K的最大数值和 题目要求 解题思路 来自[宫水三叶] 从题面来看显然是一道[二维前缀和]的题目。本题预处理前缀和的复杂度为O(m* n) 搜索所有子矩阵需要枚举[矩形左上角]和[矩形右下角]&#xff0c;复杂度是 O ( m 2 ∗ n 2 ) O(m^2 * n^2) O(m2∗n2)&#xff0c…...

【js】js数组对象去重:

文章目录 一、Map()二、对象访问属性的方法三、indexOf()四、双层for循环 let arrObj [{ name: "小红", id: 1 },{ name: "小橙", id: 1 },{ name: "小黄", id: 4 },{ name: "小绿", id: 3 },{ name: "小青", id: 1 },{ na…...

python高校舆情分析系统+可视化+情感分析 舆情分析+Flask框架(源码+文档)✅

毕业设计&#xff1a;2023-2024年计算机专业毕业设计选题汇总&#xff08;建议收藏&#xff09; 毕业设计&#xff1a;2023-2024年最新最全计算机专业毕设选题推荐汇总 &#x1f345;感兴趣的可以先收藏起来&#xff0c;点赞、关注不迷路&#xff0c;大家在毕设选题&#xff…...

Phaser详解

Phaser是一个相对较新且功能强大的同步原语&#xff0c;它于Java 7中引入&#xff0c;用于协调并行任务的执行。与CyclicBarrier和CountDownLatch等传统的同步工具相比&#xff0c;Phaser提供了更灵活和更高级的功能&#xff0c;特别是在处理动态和可变的并行任务集合时。 1.P…...

2个nodejs进程利用redis 实现订阅发布

1.新建文件 redis_db.js use strict;const redis require(redis); const options {host: "127.0.0.1",port: 6379,password: "123456", // CONFIG SET requirepass "123456" }var array [] for(var i0; i<3; i){const client redis.crea…...

LeetCode——2397. 被列覆盖的最多行数

通过万岁&#xff01;&#xff01;&#xff01; 题目&#xff1a;给你一个二维数组&#xff0c;然后里面是0和1&#xff0c;然后让你从里面选择numSelect列&#xff0c;使得去掉选择的列以后不存在1的行的数量最少。思路&#xff1a; 看到这个题目&#xff0c;本来以为是每一列…...

java通过HttpClient方式实现https请求的工具类(绕过证书验证)

目录 一、引入依赖包二、HttpClient方式实现的https请求工具类三、测试类 一、引入依赖包 引入相关依赖包 <!--lombok用于简化实体类开发--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><option…...

JavaSec-RCE

简介 RCE(Remote Code Execution)&#xff0c;可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景&#xff1a;Groovy代码注入 Groovy是一种基于JVM的动态语言&#xff0c;语法简洁&#xff0c;支持闭包、动态类型和Java互操作性&#xff0c…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄

文&#xff5c;魏琳华 编&#xff5c;王一粟 一场大会&#xff0c;聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中&#xff0c;汇集了学界、创业公司和大厂等三方的热门选手&#xff0c;关于多模态的集中讨论达到了前所未有的热度。其中&#xff0c;…...

利用ngx_stream_return_module构建简易 TCP/UDP 响应网关

一、模块概述 ngx_stream_return_module 提供了一个极简的指令&#xff1a; return <value>;在收到客户端连接后&#xff0c;立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量&#xff08;如 $time_iso8601、$remote_addr 等&#xff09;&a…...

Objective-C常用命名规范总结

【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名&#xff08;Class Name)2.协议名&#xff08;Protocol Name)3.方法名&#xff08;Method Name)4.属性名&#xff08;Property Name&#xff09;5.局部变量/实例变量&#xff08;Local / Instance Variables&…...

【git】把本地更改提交远程新分支feature_g

创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

【决胜公务员考试】求职OMG——见面课测验1

2025最新版&#xff01;&#xff01;&#xff01;6.8截至答题&#xff0c;大家注意呀&#xff01; 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:&#xff08; B &#xff09; A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

DBAPI如何优雅的获取单条数据

API如何优雅的获取单条数据 案例一 对于查询类API&#xff0c;查询的是单条数据&#xff0c;比如根据主键ID查询用户信息&#xff0c;sql如下&#xff1a; select id, name, age from user where id #{id}API默认返回的数据格式是多条的&#xff0c;如下&#xff1a; {&qu…...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点&#xff0c;但无自动故障转移能力&#xff0c;Master宕机后需人工切换&#xff0c;期间消息可能无法读取。Slave仅存储数据&#xff0c;无法主动升级为Master响应请求&#xff…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

Rust 开发环境搭建

环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行&#xff1a; rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu ​ 2、Hello World fn main() { println…...