浅谈JavaScript的事件(事件委托)

  事件处理程序为Web程序提供了系统交互,但是如果页面中的事件处理程序太多,则会影响页面的性能。每个函数都是对象,都会占用内存,内存中对象越多,性能越差。需要事先为DOM对象指定事件处理程序,导致访问DOM的次数增多,会延迟整个页面的交互就绪时间。

  • 事件委托

  对事件处理程序过多的解决方案是使用事件委托。事件委托利用了事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。比如click事件会一直冒泡到document,也就是说我们只需为整个页面指定一个onclick事件处理程序,而不必为每个需要点击事件的元素单独添加。

1 <ul id="ul1">
2             <li id="li1">111</li>
3             <li id="li2">222</li>
4         </ul>

  例如上面的代码,如果我们采用常规手段来添加事件处理程序,我们需要为每个li都添加事件。但是如果采用冒泡,我们只需要指定一个事件处理程序,并且能够实现同样的功能。

 1 var oUl = document.getElementById("ul1"); 
 2             EventUtil.addEvent(oUl, "click", function(ev) {    
 3                 var ev = EventUtil.getEvent(ev);    
 4                 var target = EventUtil.getTarget(ev);    
 5                 if(target.id == 'li1') {       
 6                     console.log("1");   
 7                 }
 8                 else if(target.id=="li2"){
 9                     console.log("2");
10                 }  
11             });

  上面的代码中,通过事件冒泡为ul1指定了事件处理程序,在我们单击li的时候通过事件冒泡也会触发该事件,并且能够通过target来获取当前单击的元素对象。通过元素id,为每个元素执行不同的if语句。

并不是所有的事件都适合使用事件委托,比较适用的事件是:mouseup、mousedown、click、keyup、keydown和keypress。虽然mouseover和mouseout也支持事件冒泡,但是如果使用事件委托则处理就比较麻烦,而且需要计算鼠标的位置以及元素的位置(当鼠标从一个元素移到其子节点,或者移出元素都会触发mouseout事件)。

 1 var oUl = document.getElementById("ul1"); 
 2             EventUtil.addEvent(oUl, "mouseout", function(ev) {    
 3                 var ev = EventUtil.getEvent(ev);    
 4                 var target = EventUtil.getTarget(ev);    
 5                 if(target.id == 'li1') {       
 6                     console.log("1");   
 7                 }
 8                 else if(target.id=="li2"){
 9                     console.log("2");
10                 }  
11             });

  比如上面的代码,当鼠标移到li元素的时候会触发mouseout,鼠标移出ul元素的时候也会触发mouseout事件。

  • 移除事件处理程序

  前文已经讲过事件的添加以及事件的移除。对于页面的事件处理程序太多,会影响页面的性能,除了使用事件委托之外,还可以将一些事件移除。内存中留有的一些过时的用不到的事件处理程序也是造成Web页面和内存性能的主要问题。

  我们移除页面中的元素时候,可以通过removeChild和replaceChild方法,但有时候也会使用innerHTML来替换元素。如果某个元素有事件处理程序,通过innerHTML来替换,则事件处理程序依然存在,那么该事件处理程序已经使用不到,但是它也无法被回收,会一直占用内存空间。

  

1 <div id="firstdiv">
2             <input type="button" id="btnadd" value="添加" />
3         </div>
1 EventUtil.addEvent(document.getElementById("btnadd"),"click",function(event){
2                 document.getElementById("firstdiv").innerHTML="processing";
3             });

  上面的代码中为btnadd元素绑定了单击事件,单击的时候通过innerHTML移除了该元素,但是元素的事件处理程序并没有移除,依然留在内存中。

  

1 var callback =function(event){
2                 EventUtil.removeEvent(document.getElementById("btnadd"),"click",callback);
3                 document.getElementById("firstdiv").innerHTML="processing";
4             }
5             EventUtil.addEvent(document.getElementById("btnadd"),"click",callback);

  上面的代码,我们在元素移除之前,手动移除了元素的事件处理程序。这样确保内存中也移除了该事件处理程序,而从DOM中移除按钮也非常彻底。

posted on 2018-02-23 09:29  水击三千  阅读(310)  评论(0编辑  收藏  举报

导航