美文网首页
JS事件委托(事件代理)

JS事件委托(事件代理)

作者: 寒o_0 | 来源:发表于2020-02-27 12:36 被阅读0次

什么是事件委托?

举个例子,我们要实现点击 li 时打印其id

<ul id="myList">
  <li id="a">aaa</li>
  <li id="b">bbb</li>
  <li id="c">ccc</li>
</ul>

一般我们会给每一个li绑定一个事件处理函数

let myList = document.getElementById('myList')
let oLi = myList.getElementsByTagName('li')

for (let i = 0; i < oLi.length; i++ ) {
  oLi[i].addEventListener('click', function () {
    console.log(this.id)
  })
}

这种方法存在两个问题:

  1. 如果有很多 li,大量的事件处理程序会占用不少内存,绑定事件处理程序也需要访问很多次DOM,页面的整体性能将大大降低
  2. 后续新增的li没有绑定事件处理程序

事件委托就是解决这两个问题的一种方案,方式如下

let myList = document.getElementById('myList')

myList.addEventListener('click', function (e) {
  console.log(e.target.id)
})

事件委托的原理:

由于事件冒泡的机制,当我们点击li时,ul也会触发click事件,所以我们只需给ul绑定事件处理程序,就能监听所有li的click事件,而且是动态的,新增的li也能被监听;
但如何判断我们点击的是哪个 li 呢?Event对象提供了一个属性叫target,该属性包含事件的目标,也就是事件源,通过target可以得到事件的目标节点

常见的问题

1.如果每个li被点击的效果不一样,怎么办呢?

let myList = document.getElementById('myList');

myList.addEventListener('click', function (e) {
  let target = e.target
  if (target.nodeName.toLowerCase() === 'li') {
    switch(target.id) {
      case 'a': 
        console.log('a1');
        break;
      case 'b': 
        console.log('b2');
        break;
      case 'c': 
        console.log('c3');
        break;
    }
  }
})

2.如果li还有其他子节点怎么办?

<ul id="myList">
  <li id="a">
    <p>aaa</p>
  </li>
  <li id="b">
    <div>
      <p>bbb</p>
    </div>
  </li>
  <li id="c">ccc</li>
</ul>
let myList = document.getElementById('myList');

myList.addEventListener('click', function (e) {
  let target = e.target
  while (target !== myList) {
    if (target.tagName.toLowerCase() === 'li') {
      console.log(target.id)
      break
    }
    target = target.parentNode
  }
})

核心是通过while和target.parentNode(或parentElement)遍历事件流上的所有节点

JQuery的事件委托

$('#myList').on('click', 'li', function (e) {
  console.log(e.currentTarget.id)
  console.log(this.id)
})

on()方法语法如下
$(selector).on(event,childSelector,data,function)
childSelector:指定被代理的后代元素

这里的this和e.currentTarget指向childSelector

React 与 Vue 中是否有必要使用事件委托?

React 内部自定义了一套事件系统,利用事件委托机制在Document上统一监听DOM事件,再根据触发的target将事件分发到具体的组件实例,所以无需我们再使用事件委托

Vue 内部没有做事件委托,但做了一些优化,在 v-for 中每个侦听器都使用同一个回调,并会自动处理监听器的创建和销毁,所以一般情况下没有必要使用事件委托

参考:
js中的事件委托或是事件代理详解 - 凌云之翼 - 博客园
谈谈React事件机制和未来(react-events) - 荒山的文章 - 知乎
https://www.runoob.com/jquery/event-on.html
https://forum.vuejs.org/t/is-event-delegation-necessary/3701/3
《JavaScript高级程序设计》

相关文章

  • JS写事件代理

    js中的事件委托或是事件代理详解

  • js 事件委托 事件代理

    js 事件委托 事件代理 JavaScript高级程序设计上解释:事件委托就是利用事件冒泡,只指定一个事件处理程序...

  • js事件委托/事件代理

    事件委托就是利用事件冒泡,只指定一个时间处理程序就可以管理某一类型的所有事例。 优点:提高性能 JavaScrip...

  • JS事件委托(事件代理)

    什么是事件委托? 举个例子,我们要实现点击 li 时打印其id 一般我们会给每一个li绑定一个事件处理函数 这种方...

  • js事件委托(事件代理)

    定义:事件委托就是在DOM事件的冒泡阶段,把具体dom上发生的事件委托给父元素或祖先元素去处理。原理:要了解委托的...

  • js事件委托(事件代理)

    起因: 1、这是前端面试的经典题型,要去找工作的小伙伴看看还是有帮助的; 2、其实我一直都没弄明白,写这个一是为了...

  • js事件深入学习

    JavaScript的事件机制包含,事件绑定、事件监听、事件委托(事件代理)等 js中的事件流 ① .冒泡:当下级...

  • 事件委托

    还有很多要学,要加油哇。回正题。参考: js中的事件委托或是事件代理详解 1、基本概念事件委托就是利用事件冒泡,只...

  • 概念

    事件委托,事件代理 事件代理又称之为事件委托。是JavaScript中常用绑定事件的常用技巧。顾名思义,“事件代理...

  • js事件委托

    前言 事件委托,也叫事件代理,是js事件中的一种常用技巧。事件委托的原理就是利用冒泡事件的机制,为一些节点的祖先节...

网友评论

      本文标题:JS事件委托(事件代理)

      本文链接:https://www.haomeiwen.com/subject/ucythhtx.html