事件委托

为什么要进行事件委托?事件委托是什么?
由于事件处理程序可以为现代的web应用程序提供交互能力,因此在添加页面上的事件处理程序的数量没有一个严格的限制,将会直接关系到页面的整体运行性能。导致这个问题是多方面的。首先,每个函数都是对象,都会占用内存;内存中的对象越多,性能就越差。其次,必须事先指定所有事件处理程序而导致的DOM访问次数,会延迟整个页面的交互就绪时间。
所以对于“事件处理程序过多”的解决方案就是事件委托也称为事件代理。事件委托利用了事件冒泡,指定一个事件处理程序,就可以管理某一类型的所有事件。以下面的代码为例:

   <ul id = "myLinks">
            <li id = "mylink1">Link1</li>
            <li id = "mylink2">Link2</li>
            <li id = "mylink3">Link3</li>
    </ul>
以上的三个li元素都添加了点击后执行相同的个操作,一般的做法就是获得它们所有的id,再逐个添加事件,如下:

window.onload = function(){
var list= document.getElementById("myLinks");
var Li = list.getElementsByTagName('li');
for(var i=0;i<Li.length;i++){
    Li[i].onclick = function(){
       //do something
    }
}

}
大多数人都会这样实现。我们看看有多少次的dom操作,首先要找到ul,然后遍历li,然后点击li的时候,又要找一次目标的li的位置,才能执行最后的操作,每次点击都要找一次li;

那么我们用事件委托的方式做又会怎么样呢?

window.onload = function(){
var list = document.getElementById(“myLinks”);
list.onclick = function(){
//do something
}
}
在这里找到了<li>的父元素<ul>对父元素添加事件,由于冒泡原理,每次点击<li>的时候就会向父级冒泡,最终触发父级的事件。
那么这里是相同的操作,当子元素点击都会触发不同的操作,怎么处理?同样是最上面的例子,很多人可能会这样做:

    var item1 = document.getElementById("mylink1");
    var item2 = document.getElementById("mylink2");
    var item3 = document.getElementById("mylink3");

    item1.onclick = function(){
        alert("Link1");
    }
        item2.onclick = function(){
        alert("Link2");
    }
        item3.onclick = function(){
        alert("Link3");
    }

如果在一个复杂的web应用程序中,对所有可单击元素都采用这种方式,结果就会有数不清的代码用于添加事件处理程序。
所以解决办法就是利用事件委托技术,将同一类型的事件处理程序进行统一管理。
利用事件委托,只需在DOM树中尽量高的层次上添加一个事件处理程序。将上面的例子改造为:

var list = document.getElementById("myLinks");
list.onclick = function(event){
 var event = event || window.event; 
 var target = event.target || event.srcElement;

        switch(target.id){
            case  "mylink1":
                  //do something;
                    break;
            case  "mylink2":
                    //do something;
                    break;

            case  "mylink3":
                    //do something
                    break;
    }

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

我们采用事件委托只为 <ul> 元素添加了一个onclick事件处理程序。所有列表项都是这个元素的子节点,而它们的事件会冒泡,所以单击事件最终会被这个函数处理。用事件委托就可以只用一次dom操作就能完成所有的效果,比上面的性能肯定是要好一些的 。

当用事件委托的时候,根本就不需要去遍历元素的子节点,只需要给父级元素添加事件就好了,其他的都是在js里面的执行,这样可以大大的减少dom操作,这才是事件委托的精髓所在。
最适合事件委托技术的事件包括:click、mousedown、mouseup、keydown、keyup、keypress等。虽然mouseover和mouseout事件也冒泡,但是要适当处理它们并不容易,而且经常需要计算元素的位置。
如果可行的话,为document对象添加一个事件处理程序,用以处理页面上发生的某种特定类型的事件,这样做将会有以下优点:
1.document对象很快就可以访问,而且可以在页面生命周期的任何时间点上为它添加事件处理程序(无需等待load或者DOMContentLoaded事件),简单地说,只要单击的元素呈现在页面上,就可以立即具备适当的功能。
2.页面中设置事件处理程序所需的时间更少。只添加一个事件处理程序 所需的DOM引用更少,所花的时间也更少。
3.整个页面占用的内存空间更少,能够提升整体性能。

移除事件处理程序

每当将事件处理程序指定给元素时,运行中的浏览器代码与支持页面交互的js代码之间就会建立一个链接,这种连接越多,页面执行起来就越慢。所以就可以采用事件委托技术,限制建立连接的数量,另外在不需要的时候移除事件处理程序。
内存中留有那些过时不用的“空事件处理程序”也是造成web应用程序内存性能问题的原因。主要有两个方面:
1. 从文档中移除带有事件处理的元素时,可能是 纯粹的DOM操作。例如使用removeChild(),replaceChild()方法,更多的发生在innerHTML替换页面的某一部分的时候,如果带有事件处理的元素被innerHTML替换了,那么原来元素中的事件处理程序可能无法被当做垃圾回收,针对这一事件在,在替换前应手工删除。(手工删除:哪种方法添加的事件就用哪种方法删除,前篇已经讲到了三种事件的添加及移除)
2. 卸载页面时也容易导致“空事件处理程序”,如果在页面卸载之前没有清理干净事件处理程序,它们就会滞留在内存中,每次加载完页面再卸载,就会导致内存中滞留的对象数目增加。所以解决办法就是在页面卸载之前通过onunload事件处理程序移除所有事件处理程序。如果要unload的事件进行了委托,那么就再次表现了事件委托的优势——需要跟踪的事件处理程序少,移除越容易。移除时,只要通过onload添加,就通过onunload移除。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值