JS事件委托

1,365 阅读3分钟

       事件委托又叫事件代理,就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。

使用原因

一般来说,DOM需要有事件处理程序,我们都会直接给它设定事件处理程序就好了,但是如果有很多DOM需要添加处理事件,比如,一个ul下有很多个li,需要给每个li都添加相同的点击事件,这时候我们通常会用for循环的方法,遍历所有元素,然后给他们添加点击事件,虽然看似内心毫无波澜很合理的做法,背后实则存在着巨大的性能弊端。

在JS中,添加到页面上的事件处理程序数量将直接关系到页面的整体运行性能,因为需要不断的与DOM节点进行交互,所以访问DOM的次数越多,引起浏览器重绘与重排的次数也就越多,就会延长整个页面的交互就绪时间,这就是为什么性能优化的主要思路就是从减少DOM操作的角度去入手的原因。

这种情况,如果用时间委托,就会将所有的操作都放到JS程序里面,与DOM的操作就只需要交互一次,这样就能大大的减少与DOM的交互次数;并且,每一个函数都是一个对象,是对象就会占用内存,对象越多,内存占用率就越大,性能自然就会越差,如果使用事件委托,我们就可以只对它的父级这一个对象进行操作,这样我们就值需要一个内存空间就够了,大量节省了内存空间,提高整体页面的性能了。

比如下面的代码。相信很多人都是这么实现的,会造成多次的DOM操作。这样性能会很差。

HTML

<div id="box">
  <ul id="ul-list">
    <li>第一个</li>
    <li>第二个</li>
    <li>第三个</li>
    <li>第四个</li>
    <li>第五个</li>
  </ul>
</div>

JS

window.onload = function (){
  var ulDom = document.getElementById("ul-list");
  var liDomList = ulDom.getElementsByTagName("li");
  for (var i in liDomList) {
    liDomList[ i ].index = Number(i) + 1;
    liDomList[ i ].onclick = function (){
      alert("你点击了第" + this.index + "个li");
    }
  }
}

事件委托的实现原理

事件委托是利用事件冒泡的原理来实现的,当你点击最下面的节点的时候,事件就会逐步向上传播事件,一层一层的向外执行,所以当我们给最外面的ul加点击事件,那么里面的li在执行点击事件的时候都会冒泡到最外层的ul上,就会被触发,事件委托:元素委托它们的父级元素代为执行事件。

window.onload = function (){
  var ulDom = document.getElementById("ul-list");
  ulDom.onclick = function ( ev ){
    var ev = ev || window.event;
    var target = ev.target || ev.srcElement;
    alert(target.innerText);
  }
}

这里用父级ul做事件处理,当li被点击时,由于冒泡原理,事件就会冒泡到ul上,因为ul上有点击事件,所以事件就会被触发,当然,为了避免和ul的点击事件一起触发,所以我们可以利用Event对象。

Event对象提供了一个属性叫target,可以返回事件的目标节点,我们称为事件源,也就是说,target就可以表示为当前事件操作的DOM,但是不是真正操作DOM,target有兼容性问题,标准浏览器用e.target,IE浏览器用event.srcElement,这样就可以获取当前事件执行的节点对象。

<body>
<div id="box">
  <ul id="ul-list">
    <li class="add">新增</li>
    <li class="edit">编辑</li>
    <li class="dele">删除</li>
  </ul>
</div>
<script>
  window.onload = function (){
    var ulDom = document.getElementById("ul-list");
    ulDom.onclick = function ( ev ){
      var ev = ev || window.event;
      var target = ev.target || ev.srcElement;
      if(target.nodeName.toLocaleLowerCase() == 'li'){
        alert('这是' + target.className + '操作');
      }
    }
  }
</script>
</body>

适合用事件委托的事件:click、mousedown、mouseup、keydown、keyup、keypress

以上就是我个人对事件委托的一些浅薄理解了,大家有更好的意见或问题欢迎下方留言~