在javasript中delegate这个词经常出现,看字面的意思,代理、委托。那么它究竟在什么样的情况下使用?它的原理又是什么?在各种框架中,也经常能看到delegate相关的接口。这些接口又有什么特殊的用法呢?这篇文章就主要介绍一下javascript delegate的用法和原理,以及Dojo,jQuery等框架中delegate的接口。
JavaScript事件代理
首先介绍一下JavaScript的事件代理。事件代理在JS世界中一个非常有用也很有趣的功能。当我们需要对很多元素添加事件的时候,可以通过将事件添加到它们的父节点而将事件委托给父节点来触发处理函数。这主要得益于浏览器的事件冒泡机制,后面会详细介绍。下面我们具体举个例子来解释如何使用这个特性。这个例子主要取自
David Walsh的相关
文章(How JavaScript Event Delegation Works)。
假设有一个 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上的时候,需要获取此Li的相关信息并飘出悬浮窗以显示详细信息,或者当某个Li被点击的时候需要触发相应的处理事件。我们通常的写法,是为每个Li都添加一些类似onMouseOver或者onClick之类的事件监听。
function addListeners4Li(liNode){ liNode.onclick = function clickHandler(){...}; liNode.onmouseover = function mouseOverHandler(){...} } 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]); } }
如果这个UL中的Li子元素会频繁地添加或者删除,我们就需要在每次添加Li的时候都调用这个addListeners4Li方法来为每个Li节点添加事件处理函数。这就添加的复杂度和出错的可能性。
更简单的方法是使用事件代理机制,当事件被抛到更上层的父节点的时候,我们通过检查事件的目标对象(target)来判断并获取事件源Li。下面的代码可以完成我们想要的效果:
// 获取父节点,并为它添加一个click事件 document.getElementById("parent-list").addEventListener("click",function(e) { // 检查事件源e.targe是否为Li if(e.target && e.target.nodeName.toUpperCase == "LI") { // 真正的处理过程在这里 console.log("List item ",e.target.id.replace("post-")," was clicked!"); } });
为父节点添加一个click事件,当子节点被点击的时候,click事件会从子节点开始向上冒泡。父节点捕获到事件之后,通过判断e.target.nodeName来判断是否为我们需要处理的节点。并且通过e.target拿到了被点击的Li节点。从而可以获取到相应的信息,并作处理。