JavaScript必会技能之事件委托详解

 更新时间:2026年03月09日 08:31:25   作者:勇宝趣学前端  
这篇文章主要介绍了JavaScript必会技能之事件委托的相关资料,事件委托是一种优化网页性能的技术,通过利用事件冒泡机制,在父元素而非每个子元素上绑定事件处理程序,文中通过代码介绍的非常详细,需要的朋友可以参考下

什么是事件委托

事件委托也叫事件代理,代理一词很好理解了。就是把自己的事情委托给另一个人去做,打个比方,比如拿快递,像在学校中一般快递都是寄到学校的各个快递点的,学生下课后到指定的地点进行取件,我们把收快递的这个事件委托给快递点,这就是一个事件委托,当然了如果能够送到宿舍最好了O(∩_∩)O哈哈~

应用场景一:不改变 DOM 结构

功能需求

事件委托的出现肯定是有他的道理的,举个例子,如果我们想要实现这么一个需求:

  • 在页面上创建一个 ul 列表。
  • 在 ul 列表下有 5 个 li标签。
  • 给每个 li 标签一个文本内容。
  • 给 li 一个点击事件,当触发后 li 标签的背景颜色变为红色。

这里简单用代码实现一下:

  • html 部分:ul>li{这是第$个 li 标签}*5

    <ul>
        <li>这是第1个 li 标签</li>
        <li>这是第2个 li 标签</li>
        <li>这是第3个 li 标签</li>
        <li>这是第4个 li 标签</li>
        <li>这是第5个 li 标签</li>
    </ul>
    
  • js 部分

    // 获取所有的 li 标签
    let lis = document.getElementsByTagName('li'); 
    // 1. 遍历 lis 给每一个 li 添加点击事件改变背景颜色
    for (let item of lis) {
        item.addEventListener("click", () => { 
            item.style.background = "red";
        });
    }
    
  1. addEventListener 第三个参数可以控制事件冒泡和事件捕获(onclick不可以),默认为 false (冒泡), true (捕获)
  2. 事件处理 this与onclick一样
  3. 可以为某个元素绑定多个事件而不会覆盖之前绑定的处理程序 (按照顺序执行,onclick不可以)

功能已经实现,但是设想一下如果有 10000 个li标签,那么我们就需要遍历 10000 次,给每一个 li 添加点击事件,每一个函数就是一个对象,每个对象都会占用内存,对象越多,内存消耗就越大,所表现出来的网站性能就越差劲。所以我们应该减少 DOM 操作。所以事件委托派上用场了。

使用事件委托

使用代码实现一下:

  • html 部分和功能需求中相同,我们主要编写 js 部分代码

  • js 部分

    // 获取 ul 标签
    let ul = document.querySelector('ul');
    // 将单击事件委托给 li 的父级 ul
    ul.addEventListener('click',(e)=>{
        // 兼容性  获取事件源
        let ev = e || window.event;
        let target = ev.target || ev.srcElement; 
        // 进行大小写转换  ==比较
        if(target.nodeName.toLowerCase() == 'li'){
            target.style.background = 'red';
        }
    })
    

    这是我理解的事件委托使用到的一个场景。

    我们也可以通过 id 去完成事件委托

  • html部分

    <ul id="myUl">
      <li id="insert">insert</li>
      <li id="delete">delete</li>
      <li id="update">update</li>
      <li id="select">select</li>
    </ul>
    
  • js 部分

      // 获取 ul 标签
      let ul = document.querySelector('ul');
      // 将单击事件委托给 li 的父级 ul
      ul.addEventListener('click',(e)=>{
          // 兼容性  获取事件源
          let ev = e || window.event;
          let target = ev.target || ev.srcElement; 
          // 通过 switch 判断是点击了哪一个 li
          switch (target.id) {
              case "insert":
                  target.innerHTML = target.innerHTML + ":添加一个文本";
                  break;
              case "delete":
                  target.innerHTML = "";
                  break;
              case "update":
                  target.innerHTML = '这是修改后的文本';
                  break;
              case "select":
                  alert('这是查询的文本');
                  break;
          }
      })
    

应用场景二:改变 DOM 结构

功能需求

  • 在页面上创建一个 button 按钮。
  • 在页面上创建一个 ul 列表。
  • 在 ul 列表下有 5 个 li标签。
  • 给每个 li 标签一个文本内容。
  • 给 button 一个点击事件,当触发后生成一个 li 插入到 ul 下的最后一个 li 后边。
  • 给 ul 下的 li 一个点击事件,当触发后 li 标签的背景颜色变为红色。

这里简单用代码实现一下:

  • html 部分:ul>li{这是第$个 li 标签}*5

    <button>添加新标签</button>
    <ul>
        <li>这是第1个 li 标签</li>
        <li>这是第2个 li 标签</li>
        <li>这是第3个 li 标签</li>
        <li>这是第4个 li 标签</li>
        <li>这是第5个 li 标签</li>
    </ul>
    
  • js 部分

    // 获取 ul 标签
    let ul = document.querySelector("ul");
    // 获取 button 按钮
    let btn = document.querySelector("button");
    btn.addEventListener("click", () => {
        // 获取 lis 的长度
        let leg = lis.length;
        // 1. 创建一个 li 标签
        let li = document.createElement("li");
        // 2. 给创建的 li 标签添加文本内容
        li.textContent = `这是第${leg + 1}个 li 标签`;
        // 3. 把创建的 li 标签挂载到 document 中
        ul.appendChild(li);
    });
    // 获取 li 标签
    let lis = document.getElementsByTagName("li");
    for (let item of lis) {
        item.addEventListener("click", () => {
            item.style.background = "red";
        });
    }
    

    存在的问题:

    清楚的发现,已经在 DOM 结构中生成的 li 点击后可以改变背景颜色,但是通过 button 按钮插入的 li 当点击后没有效果,这里我理解为,button 的点击事件并没有事件复制过去。因为在程序一加载的时候,for循环已经遍历完成。

使用事件委托

事件委托就不用担心事件复制不了的问题了,使用代码实现一下:

  • html 部分和功能需求中相同,我们主要编写 js 部分代码

  • js 部分

    // 获取 ul 标签
    let ul = document.querySelector("ul");
    ul.addEventListener("click", e => {
        let ev = e || window.event;
        let target = ev.target || ev.srcElement;
        if (target.nodeName.toLowerCase() == "li") {
            target.style.background = "red";
        }
    });
    // 获取 button 按钮
    let btn = document.querySelector("button");
    btn.addEventListener("click", () => {
        // 获取 ul 下 li 的长度
        let leg = ul.children.length;
        console.log(leg);
        // 1. 创建一个 li 标签
        let li = document.createElement("li");
        // 2. 给创建的 li 标签添加文本内容
        li.textContent = `这是第${leg + 1}个 li 标签`;
        // 3. 把创建的 li 标签挂载到 document 中
        ul.appendChild(li);
    });
    

    其他应用场景:像 Element-ui 中 Dialog 效果可以使用到事件委托,有时间封装一下 Dialog 组件。

事件委托的优缺点

优点

  1. 减少内存消耗,减少事件绑定。
  2. 给动态添加的元素绑定事件。

缺点

  1. 部分事件如 focus、blur 等无冒泡机制,所以无法委托。
  2. 事件委托有对子元素的查找过程,委托层级过深,可能会被某一层阻止掉。
  3. 频繁触发的事件,不适合事件委托。

总结

​ 事件委托固然方便,但是我们也要在合适的场景使用它,以免事倍功半。

到此这篇关于JavaScript必会技能之事件委托详解的文章就介绍到这了,更多相关js事件委托内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JavaScript canvas仿代码流瀑布

    JavaScript canvas仿代码流瀑布

    这篇文章主要为大家详细介绍了JavaScript canvas仿代码流瀑布,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-02-02
  • JavaScript常用验证函数实例汇总

    JavaScript常用验证函数实例汇总

    这篇文章主要介绍了JavaScript常用验证函数,实例汇总了如字符串验证、表单验证及js常用特效等诸多js常用验证函数及相关技巧,非常具有实用价值,需要的朋友可以参考下
    2014-11-11
  • JavaScript生成福利彩票双色球号码

    JavaScript生成福利彩票双色球号码

    无聊用javascript写了个随机产生福利彩票双色球7个数字的号码其中红色球不会重复,喜欢的可以下来看看,有意见的可以说说
    2015-05-05
  • onbeforeunload与onunload事件异同点总结

    onbeforeunload与onunload事件异同点总结

    本文对onbeforeunload与onunload事件的异同点、触发于、可以用在哪些元素以及解决刷新页面时不调用onbeforeunload等等,感兴趣的朋友可以参考下哈
    2013-06-06
  • JavaScript剩余操作符Rest Operator详解

    JavaScript剩余操作符Rest Operator详解

    在本篇文章里小编给各位分享的是关于JavaScript剩余操作符Rest Operator知识点用法总结,有需要的朋友们跟着学习下。
    2019-07-07
  • JavaScript中可选链操作符(?.)的实用指南

    JavaScript中可选链操作符(?.)的实用指南

    在现代前端开发中,高达 68%的 JavaScript 运行时错误源于访问未定义属性,本文将深入解析可选链(?.)如何从根本上解决这一问题,并结合实际场景、底层原理与最佳实践,助你彻底规避TypeError陷阱,需要的朋友可以参考下
    2025-06-06
  • 详解TypeScript编译TSX文件的方法

    详解TypeScript编译TSX文件的方法

    因为使用 Cycle.js 的 Vite + TSX 所以想详细的探索 TSX 在 TS 配置中的编译情况,本文主要讲解 tsconfig 和 tsx 编译与配置,以常见的框架 PReact 的虚拟 DOM + TSX 组合、snabbdom + TSX 组合不同的配置以及编译输出
    2023-09-09
  • JS鼠标3次点击事件实现代码及扩展思路

    JS鼠标3次点击事件实现代码及扩展思路

    这篇文章主要介绍了JS鼠标3次点击事件实现及扩展思路,需要的朋友可以参考下
    2017-09-09
  • 实例分析js事件循环机制

    实例分析js事件循环机制

    这篇文章主要介绍了js事件循环机制,并通过实例分析了用法和技巧,一起学习分享下。
    2017-12-12
  • js函数内变量的作用域分析

    js函数内变量的作用域分析

    这篇文章主要介绍了js函数内变量的作用域分析,以实例形式简单分析了js函数的变量调用顺序,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-01-01

最新评论