JavaScript中事件委托的示例详解
作者:前端西瓜哥 发布时间:2024-08-13 02:22:12
大家好,我是前端西瓜哥。今天我们来认识一下事件委托。
所谓事件委托,就是将原本应该在当前元素绑定的事件,放到它的祖先元素上,让祖先元素来委托处理。
事件流
事件流指从页面中接收事件的顺序,也可理解为事件在页面中传播的顺序。
事件流由两阶段组成:
捕获事件
冒泡事件
我们通常用 addEventListener
给元素添加事件:
document.querySelector('#card')addEventListener(
'click',
function (event) {
console.log('div#card 冒泡点击', event);
},
false
);
第一个参数是事件名,第二个参数是事件响应函数,可以拿到当前的事件对象。
第三个参数是可选的,表示监听的是否为捕获阶段,false为冒泡阶段,也是默认值,true 为捕获阶段。我们常用的是冒泡阶段。
当我们点击元素时,就会执行这个函数。
假设我们的 DOM 结构如下:
<html>
<head>
<title>前端西瓜哥</title>
<meta charset="UTF-8" />
</head>
<body>
<div id="app">
<div id="box-1">
<div id="card">card</div>
</div>
<div id="box-2"></div>
</div>
</body>
</html>
现在我们点击 card 文字时,DOM 就会产生事件流。
事件流首先会进入 捕获阶段,从根节点往目标元素(div#card
)移动,依次经过为:
window
document(文档根元素,在 HTML 中没有显式声明)
document.documentElement(
<html>
)document.body(
<body>
)...
目标元素
div#card
和调用事件对象的 event.composedPath() 方法拿到的 事件路径 类似。
window 看起来是个全局变量,但它也是可以绑定事件的,比如窗口大小改变的 resize 事件就只能绑定到 window 上,而不能绑定到 document 上。
然后再执行 冒泡阶段,然后反着再经过一遍这些节点。
我们会根据事件流经过的顺序,依次执行这些节点上绑定的对应事件函数。
事件委托
假如我有一个好友列表,我希望点击 “聊天” 按钮,拿到对应用户 id,创建并进入到对应用户的聊天会话中。
<ul>
<li>前端西瓜哥<button>聊天</button></li>
<li>fe_watermelon<button>聊天</button></li>
<!-- ... -->
<li>老王<button>聊天</button></li>
</ul>
最直接的方式是给所有的 button 元素都绑定各自的事件。
节点少的时候还好,如果节点多达上千上万个,就需要声明相当多的事件函数,比较消耗内存。而且 如果列表经常发生动态变更,也会导致大量事件监听的移除和绑定。
在这种情况下,事件委托就大有可为了。
事件委托正是利用事件流的冒泡特性,将本来要绑定到多个元素的事件函数,委托到了其祖先元素上。
在上面这个例子中,我们可以将事件绑定到 ul 节点上,执行函数时,通过 event 对象拿到必要的信息,进行统一的操作。
document.querySelector('ul').addEventListener('click', (event) => {
const target = event.target;
const userId = target.getAttribute('data-user-id');
if (userId) {
joinChat(userId);
}
});
通过 event.target
我们能获得这次事件流的目标节点,然后从该节点对象中提取出需要的信息。
在这里我们需要拿到用户 id,所以需要给 button 元素添加类似 data-user-id
的自定义属性,像这样子:
<ul>
<li>前端西瓜哥<button data-user-id="5">聊天</button></li>
<li>fe_watermelon<button data-user-id="99">聊天</button></li>
<!-- ... -->
<li>老王<button data-user-id="63">聊天</button></li>
</ul>
这样,不管 li 有多少,更新多频繁,我们只需要维护一个函数就够了。
结尾
事件委托,其实就是将原本应该绑定在子元素的的大量类似的事件监听函数,改为绑定到父元素或祖先元素上,委托祖先元素来处理。
不过在实际开发中,需要用到事件为委托的场景还是比较少,因为我们的列表通常不会太长。
来源:https://juejin.cn/post/7121690490088456200


猜你喜欢
- 本文实例讲述了Python实现的数据结构与算法之基本搜索。分享给大家供大家参考。具体分析如下:一、顺序搜索顺序搜索 是最简单直观的搜索方法:
- 背景目前手上有一个小程序的项目,希望转发时分享消息的界面能够自定义,然而微信小程序只提供设置图片的url和title。 /**
- 关于DHT协议DHT协议作为BT协议的一个辅助,是非常好玩的。它主要是为了在BT正式下载时得到种子或者BT资源。传统的网络,需要一台中央服务
- 这篇文章主要介绍了Python实现自定义读写分离代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的
- wlile循环while True表示永远为真,不管是什么条件都会向下执行,下面是写的一个例子。#!/usr/bin/env pythona
- 前言首先声明,本工具仅仅为学习之用,不涉及版权问题,因为百度音乐里面的歌曲本身是可以下载的,而且现在百度也提供了”百度音乐播放器”,可以通过
- 之所以有这样一篇文章,是因为在前几天的一个晚上,要下班的时候,业务方忽然有一个需求,是需要恢复一个表里面的数据,当时问了下情况
- 需求:需求简单:但是感觉最后那部分遍历有意思:S型数组赋值,考虑到下标,简单题先实现个差不多的m = 5cols = 9rows = 4nu
- 前文已述,因为需要测试mysql的主从配置方案,所以要安装多个mysql。这次是在ubuntu kylin 14.10上安装多个mysql
- WebDriver简介selenium从2.0开始集成了webdriver的API,提供了更简单,更简洁的编程接口。selenium web
- 分页的首页<meta http-equiv="Content-Type" content="text/h
- ROC曲线绘制要点(仅记录)1、ROC用于度量模型性能2、用于二分类问题,如若遇到多分类也以二分类的思想进行操作。3、二分类问题代码实现(至
- 根据google最新的算法规则:用户行为模式的重视程度越来越高,这也就要求网页设计的时候应注意“合理的网页结构”,SEO业界也有个共识“网页
- 使用 Appium安装一下 Python 用到的模块pip install Appium-Python-Client获取好友列表在 Pych
- Python + OpenCV 直接上代码import cv2 import numpy as np from matplotlib imp
- 线程池的概念是什么?在面向对象编程中,创建和销毁对象是很费时间的,因为创建一个对象要获取内存资源或者其它更多资源。在Java中更是 如此,虚
- 自己在刚学习python时写的,中途遇到很多问题,查了很多资料,下面就是我爬取租房信息的代码:链家的房租网站两个导入的包1.requests
- 前言相信大家初入某个项目,一般都要看代码。有时候,想把代码文件打印下来看,不过一般代码文件数量都在两位数或更多,逐一打开、打印,确实太耗费精
- 目录step1 搭建框架step2 填充搭建好了的Promise框架总结step1 搭建框架1. 首先我们需要在这里放置一个promise函
- 在布尔索引中,我们将根据 DataFrame 中数据的实际值而不是它们的行/列标签或整数位置来选择数据子集。在布尔索引中,我们使用布尔向量来