在JS中delegate(委托,代理) 这个词经常出现,看字面的意思,代理、委托。那么它究竟在什么样的情况下使用?它的原理又是什么?在各种框架中,也经常能看到delegate相关的接口。这些接口又有什么特殊的用法呢?这篇博客就主要介绍一下javascript中 delegate的用法和原理。
事件代理
当我们需要对很多元素添加事件的时候,可以通过将事件添加到它们的父节点而将事件委托给父节点来触发处理方法。这主要得益于浏览器的事件冒泡机制。
假设有一个UL的父节点,包含多个LI的子节点。
<ul id="parent-list">
<li id="post-1">Item 1</li>
<li id="post-2">Item 2</li>
<li id="post-3">Item 3</li>
<li id="post-4">Item 4</li>
<li id="post-5">Item 5</li>
<li id="post-6">Item 6</li>
</ul>
当我们要为LI注册事件的时候通常都是添加事件进行监听
function addListenersEvent(liNode){
liNode.onclick = function(){...};
}//为LI添加事件
window.onload = function(){
var ulNode = document.getElementById("parent-list");
var liNodes = ulNode.getElementByTagName("Li");
for(var i=0, l = liNodes.length; i < l; i++){
addListeners4Li(liNodes[i]);
}
}
如果这些LI频繁地添加或者删除,每次触发时都将调用addListenersEvent这个方法来为每个LI节点添加事件,这就添加了程序的复杂度和出错的可能性。
为此,更简单的方法是通过事件委托
var aLi = document.querySelectorAll('#parent-list li');
var oUl = document.querySelector('#parent-list');
oUl.onclick = function(e){
e = window.event || e;
var id = e.target.id;
console.log(id.replace('post-',""));
}//通过事件冒泡的机制给父级添加事件然后再判断事件目标即为事件代理
事件冒泡
冒泡机制是JS中非常有趣的事情。
事件捕获:当某个元素触发某个事件(如onclick),顶层对象document就会发出一个事件流,随着DOM树的节点向目标元素节点流去,直到到达事件真正发生的目标元素。在这个过程中,事件相应的监听函数是不会被触发的。
事件目标:当到达目标元素之后,执行目标元素该事件相应的处理函数。如果没有绑定监听函数,那就不执行。
事件起泡:从目标元素开始,往顶层元素传播。途中如果有节点绑定了相应的事件处理函数,这些函数都会被一次触发。如果想阻止事件起泡,可以使用e.stopPropagation()(Firefox)或者e.cancelBubble=true(IE)来阻止事件的冒泡传播。
优缺点
优点
通过上面的介绍,大家应该能够体会到使用事件委托对于web应用程序带来的几个优点:
- 1.管理的函数变少了。不需要为每个元素都添加监听函数。对于同一个父节点下面类似的子元素,可以通过委托给父元素的监听函数来处理事件。
- 2.可以方便地动态添加和修改元素,不需要因为元素的改动而修改事件绑定。
- 3.JavaScript和DOM节点之间的关联变少了,这样也就减少了因循环引用而带来的内存泄漏发生的概率。
缺点
- 1.事件代理的应用有局限性,如果把所有事件都用代理就可能会出现事件误判,即本不用触发事件的被绑上了事件。
- 2.事件委托基于冒泡,对于不冒泡的事件不支持。
- 3.层级过多时,冒泡过程中,可能会被某层阻止掉。
- 4.代理层级不可过多。
- 5.语义化不明显容易造成误操作。