〖大前端 - 基础入门三大核心之JS篇㊹〗- DOM事件委托

  • 说明:该文属于 大前端全栈架构白宝书专栏,目前阶段免费如需要项目实战或者是体系化资源,文末名片加V!
  • 作者:不渴望力量的哈士奇(哈哥),十余年工作经验, 从事过全栈研发、产品经理等工作,目前在公司担任研发部门CTO。
  • 荣誉:2022年度博客之星Top4、2023年度超级个体得主、谷歌与亚马逊开发者大会特约speaker全栈领域优质创作者

  • 🏆 白宝书系列
    • 🏅 启示录 - 攻城狮的自我修养
    • 🏅 Python全栈白宝书
    • 🏅 ChatGPT实践指南白宝书
    • 🏅 产品思维训练白宝书
    • 🏅 全域运营实战白宝书
    • 🏅 大前端全栈架构白宝书


文章目录

  • ⭐ DOM事件委托

⭐ DOM事件委托

事件委托可以帮助解决添加事件监听的两个问题:

  1. 批量添加事件监听大量占用内存会出现的性能问题
  2. 动态添加的元素必须添加事件监听,不能获得事件监听。

下面举两个案例来分别介绍着两个问题。

**案例一,批量添加事件监听会遇到性能问题:**页面上有一个无序列表,它内部共有20个<li>元素,请批量给它们添加点击事件监听,实现效果:点击哪个<li>元素,哪个<li>元素就变红。

题目分析:可以使用getElementsByTagName可以获取到li的数组,然后通过遍历的方式循环添加事件监听

<body><div><ul id="list"><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li></ul></div><script>var oList = document.getElementById('list');var lis = oList.getElementsByTagName('li');for (var i = 0; i < lis.length; i++) {lis[i].onclick = function () {//在这个函数中,this表示点击的这个元素,this涉及函数上下文的相关知识,我们在“面向对象”中再介绍this.style.color = 'red';};};</script>
</body>

image-20230423174447970

上面案例中,每一个事件监听注册都会消耗一定的系统内存,而批量添加事件会导致监听数量太多,内存消耗会非常大。并且每个事件处理函数都是不同的函数,这些函数本身也会占用内存。

**案例二,页面元素是动态添加的,每个元素都需要添加事件监听:**页面上有一个无序列表,它内部没有<li>元素,请制作一个按钮,点击这个按钮就能添加一个<li>元素。并且要求每个增加的<li>元素也要有事件监听,实现效果点击哪个<li>元素,哪个<li>元素就变红

题目分析:li的数量不是固定的,没办法使用循环遍历的方式去批量添加事件监听。我们给新创建的li节点添加事件监听

<body><button id="btn">点击我添加列表项</button><div><ul id="list"></ul></div><script>var oBtn = document.getElementById('btn');var oList = document.getElementById('list');oBtn.onclick = function () {//创建一个孤儿节点var oLi = document.createElement('li');oLi.innerHTML = '我是列表项';//上树oList.appendChild(oLi);//添加事件监听oLi.onclick = function () {oLi.style.color = 'red';};};</script>
</body>

上面案例中,同样会出现性能问题,因为每个事件处理函数都会占用新的内存,添加几个li,就会创建几个事件监听处理函数。

为了解决上面的问题,DOM提供了一种方法,即事件委托

**事件委托:**利用事件冒泡机制,将后代元素事件委托给祖先元素

比如下图中,点击任何一个<li>元素,事件都会通过事件冒泡传给祖先元素,我们只需要给<ul>添加事件监听就可以了,而不需要给每一个<li>都添加一遍事件监听。

image-20230424101047900

事件委托需要结合e.target属性来实现

属性属性描述
target触发此事件的最早元素,即“事件源元素”
currentTarget事件处理程序附加到的元素,与this非常相似

示例代码:

<body><ul id="list"><li>我是列表项</li><li>我是列表项</li><li>我是列表项</li><li>我是列表项</li><li>我是列表项</li></ul><script>var oList = document.getElementById('list');//给ul添加事件监听oList.onclick = function (e) {//e.target就表示点击的那个元素,即事件源元素,将事件源元素变红e.target.style.color = 'red';}</script>
</body>

image-20230424102428644

可以自行尝试一下动态创建元素,点击按钮创建新的li,然后利用事件委托实现鼠标点击li时,文字变红。

事件委托的使用场景

  • 当有大量元素需要批量添加事件监听时,使用事件委托可以减少内存开销

  • 当有动态元素节点上树时,使用事件委托可以让新上树的元素具有事件监听

事件委托的注意事项

  • 注意事件是否冒泡,不能委托不冒泡的事件给祖先元素

    在鼠标事件监听中,onmouseenter和onmouseover都表示“鼠标进入”,它们有什么区别呢?答:onmouseenter不冒泡,onmouseover冒泡;onmouseenter这个属性天生就是“不冒泡”的,相当于你事件处理函数附加给了哪个DOM节点,就是哪个DOM节点自己触发的事件,没有冒泡的过程。

    示例代码:

    //因为onmouseeter不冒泡,所以鼠标进入ul中的某个li时,整个ul都会变红,因为这个事件监听针对的是ul节点元素。
    oList.onmouseenter = function (e) {   e.target.style.color = 'red';
    };
    

    解决办法:将onmouseenter换成onmouseover

  • 最内层元素尽可能不能再有额外的内层元素了,否则可能实现不了理想的效果

    比如下面的例子中,li内部还包了span标签,当鼠标点击span标签的内容时,只有span标签的变红了,而不能使整个li变红。

    <body><ul id="list"><li><span>姓名:</span>我是列表项</li><li><span>电话:</span>我是列表项</li><li><span>地址:</span>我是列表项</li><li><span>邮箱:</span>我是列表项</li><li><span>手机:</span>我是列表项</li></ul><script>var oList = document.getElementById('list');//给ul添加事件监听oList.onclick = function (e) {e.target.style.color = 'red';};</script>
    </body>
    

    image-20230424104833829

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

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

相关文章

ssl下载根证书和中间证书

为了保证客户端和服务端通过HTTPS成功通信&#xff0c;您在安装SSL证书时&#xff0c;也需要安装根证书和中间证书。本文介绍如何获取根证书和中间证书。 使用说明 如果您的业务用户通过浏览器访问您的Web业务&#xff0c;则您无需关注根证书和中间证书&#xff0c;因为根证书…

ELK高级搜索,深度详解ElasticStack技术栈-下篇

前言&#xff1a;ELK高级搜索&#xff0c;深度详解ElasticStack技术栈-上篇 14. search搜索入门 14.1. 搜索语法入门 14.1.1 query string search 无条件搜索所有 GET /book/_search结果&#xff1a; {"took" : 969,"timed_out" : false,"_shar…

力扣66. 加一

文章目录 力扣66. 加一示例代码实现总结收获 力扣66. 加一 示例 代码实现 class Solution {public int[] plusOne(int[] digits) {int ndigits.length;for(int in-1;i>0;i--){if(digits[i]!9){digits[i];for(int ji1;j<n;j){digits[j]0;}return digits;}}int[] resnew i…

python+Appium自动化:python多线程多并发启动appium服务

Python启动Appium 服务 使用Dos命令或者bat批处理来手动启动appium服务&#xff0c;启动效率低下。如何将启动Appium服务也实现自动化呢&#xff1f; 这里需要使用subprocess模块&#xff0c;该模块可以创建新的进程&#xff0c;并且连接到进程的输入、输出、错误等管道信息&…

oj塞氪算法练习

向量点积计算 import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner new Scanner(System.in);int n scanner.nextInt();int[] a new int[n];int[] b new int[n];for (int i 0; i < n; i) {a[i] scanner.nextInt();}…

汇编语言实现音乐播放器

目标程序 用汇编语言实现一个音乐播放器&#xff0c;并支持点歌 Overview 乐曲是按照一定的高低、长短和强弱关系组成的音调&#xff0c;在一首乐曲中&#xff0c;每个音符的音高和音长与频率和节拍有关&#xff0c;因此我们要分别为3首要演奏的乐曲定义一个频率表和一个节拍…

jenkins使用nexus插件

nexus介绍 Nexus 是一个强大的仓库管理工具&#xff0c;用于管理和分发 Maven、npm、Docker 等软件包。它提供了一个集中的存储库&#xff0c;用于存储和管理软件包&#xff0c;并提供了版本控制、访问控制、构建和部署等功能。 Nexus 可以帮助开发团队提高软件包管理的效率和…

解决element ui tree组件不产生横向滚动条

结果是这样的 需要在tree的外层&#xff0c;包一个父组件 <div class"tree"><el-tree :data"treeData" show-checkbox default-expand-all></el-tree></div> 在css里面这样写,样式穿透按自己使用的css编译器以及框架要求就好 &l…

基于Logistic回归实现二分类

目录 Logistic回归公式推导&#xff1a; Sigmoid函数&#xff1a; Logistic回归如何实现分类&#xff1a; 优化的方法&#xff1a; 代码&#xff1a; 1.创建一个随机数据集&#xff0c;分类直线为y2x&#xff1a; 为什么用np.hstack()增加一列1&#xff1f; 为什么返回…

Spring | Spring的基本应用

目录: 1.什么是Spring&#xff1f;2.Spring框架的优点3.Spring的体系结构 (重点★★★) :3.1 Core Container (核心容器) ★★★Beans模块 (★★★) : BeanFactoryCore核心模块 (★★★) : IOCContext上下文模块 (★★★) : ApplicationContextContext-support模块 (★★★)SpE…

【Erlang进阶学习】4、进程与消息传递

在Erlang系统中&#xff0c;进程都是轻量级的&#xff0c;意味着创建进程只需要花费微不足道的时间和极少的内存。 1、进程间不共享内存&#xff0c;而是通过消息传递来通信。 2、消息从发送进程的栈上复制到接收进程的堆上。 3、由于多个进程并发地在独立的内存空间执行&#…

RocketMQ- 深入理解RocketMQ的消息模型

1、RocketMQ客户端基本流程 ​ RocketMQ基于Maven提供了客户端的核心依赖&#xff1a; <dependency><groupId>org.apache.rocketmq</groupId><artifactId>rocketmq-client</artifactId><version>4.9.5</version> </dependency&…

PyQt6 QCheckBox复选框按钮控件

​锋哥原创的PyQt6视频教程&#xff1a; 2024版 PyQt6 Python桌面开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 PyQt6 Python桌面开发 视频教程(无废话版) 玩命更新中~共计33条视频&#xff0c;包括&#xff1a;2024版 PyQt6 Python桌面开发 视频教程(无废话…

idea通过remote远程调试云服务器

引用了第三方的包&#xff0c;调试是看不到运行流程&#xff0c;于是想到了idea的remote方法 -agentlib:jdwptransportdt_socket,servery,suspendn,address9002 写一个.sh文件并启动 nohup java -jar -agentlib:jdwptransportdt_socket,servery,suspendn,address9002 ./demo.j…

思维模型 韦伯-费希纳定律

本系列文章 主要是 分享 思维模型&#xff0c;涉及各个领域&#xff0c;重在提升认知。感觉与刺激成对数关系。 1 韦伯-费希纳定律的应用 1.1 韦伯-费希纳定律在工业设计中的应用 1 苹果公司的 iPhone 设计 苹果公司的 iPhone 设计是韦伯-费希纳定律在工业设计中的经典应用之…

剑指 Offer(第2版)面试题 15:二进制中1的个数

剑指 Offer&#xff08;第2版&#xff09;面试题 15&#xff1a;二进制中1的个数 剑指 Offer&#xff08;第2版&#xff09;面试题 15&#xff1a;二进制中1的个数解法1&#xff1a;位运算解法2&#xff1a;n & (n - 1)相关题目 剑指 Offer&#xff08;第2版&#xff09;面…

详解SpringAop开发过程中的坑

&#x1f609;&#x1f609; 学习交流群&#xff1a; ✅✅1&#xff1a;这是孙哥suns给大家的福利&#xff01; ✨✨2&#xff1a;我们免费分享Netty、Dubbo、k8s、Mybatis、Spring...应用和源码级别的视频资料 &#x1f96d;&#x1f96d;3&#xff1a;QQ群&#xff1a;583783…

1-算法基础-编程基础

1.基本数据类型 char ch A; char s[] "hello";2.const定义常量 const int N 1e5 9;//const定义常量&#xff0c;后续不可被修改 int a[N];3.万能头文件 C11等可用 #include<bits/stdc.h> using namespace std;4.typedef typedef long long kk; kk a[20…

手敲MyLinkedList,简单了解其运行逻辑

1.LinkedList的介绍和结构 LinkedList的底层是双向链表结构&#xff0c;相对于之前的单向无头非循环链表来说&#xff0c;LinkedList最大的区别就是该链表可以增加了一条链接逻辑&#xff0c;可以从最后一个节点通过地址访问来到整个链表的头结点。 通过以下集合框架&#xff0…

计算机毕业设计 基于Web的铁路订票管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…