事件委托

作者: plainnany | 来源:发表于2017-06-21 00:53 被阅读436次

在JavaScript中,事件委托Event delegation是一种事件的响应机制,当需要监听不存在的元素或是动态生成的元素时,可以考虑事件委托。

事件委托得益于事件冒泡(有关事件冒泡可以参考事件冒泡与事件捕获),当监听子元素时,事件冒泡会通过目标元素向上传递到父级,直到document,如果子元素不确定或者动态生成,可以通过监听父元素来取代监听子元素。

举个例子:
假设页面从存在一个ul,其子元素动态生成.

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>事件委托</title>
</head>
<body>
  <button>点击</button>
  <ol></ol>
  <script>
    let btn = document.getElementsByTagName('button')[0]
    let ol = document.getElementsByTagName('ol')[0]

    btn.addEventListener('click',function(){
        let li = document.createElement('li')
        let number = parseInt(Math.random() * 100, 10)
        li.textContent=number
        ol.appendChild(li)
    })
  
  <script>
</body>
</html>

当点击按钮时,ol列表中动态创建li,如果给li添加click事件,当li被点击时,li本身被删除,那么可以这样实现

 btn.addEventListener('click',function(){
      let li = document.createElement('li')
      let number = parseInt(Math.random() * 100, 10)
      li.textContent=number
      ol.appendChild(li)
      li.addEventListener('click',function(){
         li.remove();
      })
 })

但是这样就会使得给每个li都添加了click事件(或者其他的事件),而页面中的li是不确定有多少的,如果页面中生成很多的li,那么就会造成内存占用过多,因此我们可以使用事件委托来解决这个问题。

/*  
li.addEventListener('click',function(){
     li.remove();
})   
*/
 ol.addEventListener('click',function(e){
     let ele = e.target
     if(ele.tagName==='LI'){
        ele.remove()
     }
  })

在这个例子中,通过给父级而非子集添加事件,当事件被抛到更上层的父节点的时候,我们通过检查事件的目标对象target来判断并获取事件源li,当子节点被点击的时候,click事件会从子节点开始向上冒泡。父节点捕获到事件之后,通过判断e.target.nodeName来判断是否为我们需要处理的节点。并且通过e.target拿到了被点击的Li节点。从而可以获取到相应的信息,并作处理。

但是当li中有其他的标签时如span标签(或是其他的标签),直接使用上述方法就会导致事件无法被正确触发。

 btn.addEventListener('click',function(){
      let li = document.createElement('li')
      let span = document.createElement('span')
      let number = parseInt(Math.random() * 100, 10)

      span.textContent=number
      li.appendChild(span)
      ol.appendChild(li)
      ol.addEventListener('click',function(e){
         let ele = e.target
         if(ele.tagName==='LI'){
            ele.remove()
         }
      }) 
 })

此时,当点击span时,li并未被删除,点击spanli之间的部分li才会被删除,试想当子元素li中有多层嵌套时,就会导致事件无法被正确触发,因此我们需要对li进行判断,判断点击的是否是ol下的li,否则就继续查找,直到查找到li

 btn.addEventListener('click',function(){
      let li = document.createElement('li')
      let span = document.createElement('span')
      let number = parseInt(Math.random() * 100, 10)

      span.textContent=number
      li.appendChild(span)
      ol.appendChild(li)
      ol.addEventListener('click',function(e){
         let ele = e.target
         while(ele.tagName!=='LI'){
              if(ele===ol){
                 ele=null; break;
               }
               ele=ele.parentNode
          }
          ele && ele.remove()
      }) 
 })

此时不论li嵌套多少层,liclick事件都会被正确触发。

事件委托可以通过监听父级来达到监听子级的效果,减少了监听器的数量,使用内存也相对减少。当在一些难以追踪的情况下,从DOM从删除的元素仍保留「记忆」(即泄露),这些泄露的「记忆」通常与事件绑定联系在一起,使用事件委托,可以随意的对子元素进行事件绑定而不用担心忘记解绑它们的监听器。

参考:

  1. What is DOM Event delegation?
  2. How JavaScript Event Delegation Works

相关文章

  • 事件委托

    ------------------事件委托----------------- 事件: 事件委托: 原理: 冒泡 ...

  • web前端面试题@六(事件委托)

    *说到事件委托,我们首先先要知道什么是事件委托—— · 那么什么是事件委托呢??? JS里的事件委托就是当事件...

  • 前端常见面试题(十一)@郝晨光

    什么是事件委托?为什么要用事件委托? 什么是事件委托? 事件委托,又称事件代理,就是将元素的事件处理交由父元素或者...

  • 十六、DOM之事件委托 ------ 2020-01-05

    1、事件委托: 2、事件委托的优势:

  • JQuery事件委托

    JavaScript(jQuery)中的事件委托 一:什么是事件委托? 事件委托是利用事件冒泡,只指定一个事件...

  • 事件委托笔记

    事件委托原理:事件冒泡机制。 什么是事件委托: 事件委托——给父元素绑定事件,用来监听子元素的冒泡事件,并找到是哪...

  • 事件委托

    事件委托 什么是事件委托(事件代理): 事件委托就是利用事件冒泡的原理,将事件注册到父元素上,减少子元素的事件注册...

  • JavaScript 事件委托

    1. 事件委托 事件处理程序过多的解决方法就是事件委托,事件委托利用的是事件冒泡。事件冒泡:事件由最具体的元素接收...

  • 原始类型与事情委托

    1.绑定事件: 二、事件冒泡与事件捕获 事件委托 案例见事件委托 计时器

  • 事件(二)

    一.事件委托# 事件委托就是利用事件冒泡的原理,把事件添加到父元素或祖先元素上,触发执行效果 事件委托优点1、提高...

网友评论

    本文标题:事件委托

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