JS中的事件代理详解

事件代理的定义

对于事件委托或者说事件代理,有这样一段定义:

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

举个例子来说
首先我们创建一个拥有多个平行元素的列表

  • Item 1
  • Item 2
  • Item 3
  • Item 4
  • Item 5
  • Item 6

当鼠标移动到li上或者点击了li的时候,需要触发相应的事件,若果不使用事件代理,那么我们需要为每一个li都添加相应的 onClick()或者 onMouseOver()事件,代码如下:

function addListeners4Li(liNode) {
 liNode.onclick = function clickHandler(){alert('Click')};     
 liNode.onmouseover = function mouseOverHandler(){alert('MouseOver')} 
}

window.onload = function(){
  var ulNode = document.getElementById("parent-list"); 
  var liNodes = ulNode.getElementByTagName("Li"); //获取所有li节点
  for(var i=0, l = liNodes.length; i < l; i++){    
    addListeners4Li(liNodes[i]); //为每一个li节点添加监听
 }

这种方法的缺点在于

  1. 由于在javascript中,每一个函数都是一个对象,是对象就会占用内存,对象越多,占用的内存也就越大,在上面的方法中,我们创建了6个 liNodes对象,对每一个对象进行监听,但是如果li的数量特别庞大时,这种方法其实是很占用内存的
  2. 在上面的方法中,我们对每一个 liNodes对象都添加了监听,而在javascript中,添加到页面中的事件处理程序数量将直接影响程页面的整体性能,因为事件处理程序越多,与dom交互的次数就越多,引起浏览器重绘与重排的次数也就越多,从而拖慢页面的就绪时间。
  3. 如果我们需要频繁的删除和添加 li元素,就需要在每一次添加时都为其绑定事件,过于繁琐。

总结一下就是:

**1. 创建的js对象过多,占用内存

  1. JS与DOM之间的关联过多,影响性能,容易造成内存泄漏
  2. 需要管理的函数过多,对于每个元素都要添加监听**

使用事件代理可以很好的解决这两个问题,但在我们介绍事件代理之前,先要说一下事件的冒泡机制


事件的冒泡及捕获

不同的浏览器对于事件的冒泡及捕获有不同的处理方式,这里主要介绍W3C对DOM2.0定义的标准事件:

图片.png

事件捕获:当某个元素触发某个事件(如onclick),顶层对象document就会发出一个事件流,随着DOM树的节点向目标元素节点流去,直到到达事件真正发生的目标元素。在这个过程中,事件相应的监听函数是不会被触发的。

事件目标:当到达目标元素之后,执行目标元素该事件相应的处理函数。如果没有绑定监听函数,那就不执行。

事件冒泡:从目标元素开始,往顶层元素传播。途中如果有节点绑定了相应的事件处理函数,这些函数都会被一次触发。如果想阻止事件起泡,可以使用e.stopPropagation()(Firefox)或者e.cancelBubble=true(IE)来组织事件的冒泡传播。

其中 addEventListener(eventType,callBack,true | false)函数的第三个属性为 useCapture这个属性默认为 false意为在事件冒泡阶段调用事件处理函数,如果为 true则是在事件捕获阶段调用事件处理函数。


事件代理的使用

对于上面的代码,我们可以使用事件代理来进行简化,只对平行元素共同的父元素进行监听,根据其获取的源事件属性,来做出相应的处理:

document.getElementById("parent-list").addEventListener("click",function(e) { 
  //检查事件源的属性
  if(e.target && e.target.nodeName.toUpperCase == "LI") { 
    console.log("List item ",e.target.id.replace("post-")," was clicked!"); 
  }
}

在上述代码中,在 click()事件的毁掉函数中有一个源事件 e,通过查看源事件中的属性,我们可以确定当前事件是从哪个元素触发的,从而做出相应的Actions

参考:
浅析JavaScript的事件代理和委托
js中的事件委托或是事件代理详解

你可能感兴趣的:(JS中的事件代理详解)