事件委托

背景

在JS中,添加到页面上的事件处理程序都会占用内存,内存占用的越多性能就越差,且必须事先就指定好全部的事件处理程序而致使的DOM访问次数的增长会延迟整个页面的交互就绪时间。特别是对table的td和ul的li的事件处理,若是是给大量子元素添加事件,会占用大量内存。事件处理程序绑定的越多越影响性能,可是又不能说不绑定事件,因此咱们须要一种方法来减小绑定的事件,使用事件委托。node

原理

在触发DOM上的某个事件的时候,就会产生一个事件对象event,这个对象中包含着全部与事件有关的信息,其中包括致使事件的元素、事件的类型以及其余与特定事件相关的信息。避免对特定的每一个节点添加事件监听器;相反,事件监听器是被添加到它们的父元素上。事件监听器会分析从子元素冒泡上来的事件,找到是哪一个子元素的事件。web

使用

假定咱们有一个UL元素,它有几个子元素:性能

<ul id="parent-list">
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
    <li>Item 4</li>
    <li>Item 5</li>
</ul>

假设,须要触发每一个li来改变他们的背景颜色,你能够给每一个独立的li元素添加事件监听器。this

window.onload = function(){
    var oUl = document.getElementById("ul");
    var aLi = oUl.getElementsByTagName("li");

    for(var i=0; i<aLi.length; i++){
        aLi[i].onmouseover = function(){
            this.style.background = "red";
        }
        aLi[i].onmouseout = function(){
            this.style.background = "";
        }
    }
}

但有时这些li元素可能会被删除,可能会有新增,监听它们的新增或删除事件将会是一场噩梦,尤为是当你的监听事件的代码放在应用的另外一个地方时。可是,若是你将监听器安放到它们的父元素上呢?你如何能知道是那个子元素?.net

简单:当子元素的事件冒泡到父ul元素时,你能够检查事件对象的target属性,捕获真正节点元素的引用。代理

第一步是给父元素添加事件监听器。当有事件触发监听器时,检查事件的来源,排除非li子元素事件。若是是一个li元素,咱们就找到了目标!若是不是一个li元素,事件将被忽略。code

window.onload = function(){
    var oUl = document.getElementById("ul");
    var aLi = oUl.getElementsByTagName("li");

/*
这里要用到事件源:event 对象,事件源,无论在哪一个事件中,只要你操做的那个元素就是事件源。
ie:window.event.srcElement
标准下:event.target
nodeName:找到元素的标签名
*/
    oUl.onmouseover = function(ev){
        var ev = ev || window.event;
        var target = ev.target || ev.srcElement;
        //alert(target.innerHTML);
        if(target.nodeName.toLowerCase() == "li"){
        target.style.background = "red";
        }
    }
    oUl.onmouseout = function(ev){
        var ev = ev || window.event;
        var target = ev.target || ev.srcElement;
        //alert(target.innerHTML);
        if(target.nodeName.toLowerCase() == "li"){
        target.style.background = "";
        }
    }
}

总结

委托(代理)事件是那些被绑定到父级元素的事件,可是只有当知足必定匹配条件时才会被挪。这是靠事件的冒泡机制来实现的。对象

优势:blog

  • 能够大量节省内存占用,减小事件注册,好比在table上代理全部td的click事件就很是棒seo

  • 能够实现当新增子对象时无需再次对其绑定事件,对于动态内容部分尤其合适

缺点:

  • 事件代理的应用经常使用应该仅限于上述需求下,若是把全部事件都用代理就可能会出现事件误判,即本不该用触发事件的被绑上了事件。当要触发事件的标签里面还有其余标签时,不能正常的委托,由于target或srcElemt是里面的标签元素。

参考文章
http://www.webhek.com/event-d...
http://blog.csdn.net/jinboker...
http://blog.csdn.net/leo8729/...

相关文章
相关标签/搜索