JavaScript事件代理
事件代理在JS世界中一个非常有用也很有趣的功能。当我们需要对很多元素添加事件的时候,可以通过将事件添加到它们的父节点而将事件委托给父节点来触发处理函数。
这主要得益于浏览器的事件冒泡机制,下面我们具体举个例子来解释如何使用这个特性。
这个例子主要取自David Walsh的相关文章(How JavaScript Event Delegation Works)。
假设有一个 UL 的父节点,包含了很多个 Li 的子节点:
1 2 3 4 5 6 7 |
|
当我们的鼠标移到Li上的时候,需要获取此Li的相关信息并飘出悬浮窗以显示详细信息,或者当某个Li被点击的时候需要触发相应的处理事件。
我们通常的写法,是为每个Li都添加一些类似onMouseOver或者onClick之类的事件监听。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
如果这个UL中的Li子元素会频繁地添加或者删除,我们就需要在每次添加Li的时候都调用这个addListenersLi方法来为每个Li节点添加事件处理函数。
这会造成添加或者删除过程的复杂度和出错的可能性。
解决问题方法是使用事件代理机制,当事件被抛到更上层的父节点的时候,我们通过检查事件的目标对象(target)来判断并获取事件源Li。
下面的代码可以完成想要的效果:
1 2 3 4 5 6 7 8 9 |
|
在原生js中 event需要做兼容性处理
var e=window.event || e;
var target=e.target || e.srcElement;
为父节点添加一个click事件,当子节点被点击的时候,click事件会从子节点开始向上冒泡。父节点捕获到事件之后,通过判断e.target.nodeName来判断是否为我们需要处理的节点。并且通过e.target拿到了被点击的Li节点。从而可以获取到相应的信息,并作处理。
事件冒泡及捕获
浏览器的事件冒泡机制,对于事件的捕获和处理,不同的浏览器厂商有不同的处理机制,这里介绍W3C对DOM2.0定义的标准事件。
DOM2.0模型将事件处理流程分为三个阶段:
一、事件捕获阶段,
二、事件目标阶段,
三、事件起泡阶段。
如下图:
事件捕获:当某个元素触发某个事件(如onclick),顶层对象document就会发出一个事件流,随着DOM树的节点向目标元素节点流去,直到到达事件真正发生的目标元素。在这个过程中,事件相应的监听函数是不会被触发的。
事件目标:当到达目标元素之后,执行目标元素该事件相应的处理函数。如果没有绑定监听函数,那就不执行。
事件起泡:从目标元素开始,往顶层元素传播。途中如果有节点绑定了相应的事件处理函数,这些函数都会被一次触发。如果想阻止事件起泡,可以使用e.stopPropagation()(Firefox)或者e.cancelBubble=true(IE)来组织事件的冒泡传播。