首先祝大家七夕快乐。。
假如现在有一个的列表,里面可能会有若干个列表项。现在要为每一个列表项绑定相同的点击事件,现在你可能会有这几种做法:
手动为每一个列表项绑定事件;
在onload的时候,找到该列表,对其每一个子元素进行遍历,循环绑定事件;
给每一个列表项相同的类名,一次性对其进行绑定。
方法1: 对于5个以内的列表项还好,如果列表有很多,比如100+,那么这种方法很不现实,代码会非常多,而且难以维护。
方法2: 代码量看上去应该不多,但是同样会难以维护,如果是动态生成的列表项,很有可能会出现问题。最重要的,如果有大量列表项,性能会变得十分糟糕。
方法3: 原生JS不能直接选择class就不说了,即使通过匹配className的方法进行绑定,其性能只会比方法2还要差。
综上所述,JS完了(误)。
开玩笑啦,js提供一种方法叫做**事件委托**。
在讲事件委托之前,我们不妨先了解一下事件的三个阶段(对事件冒泡有所了解的可跳过此段):
捕获阶段——众里寻他千百度:
事件从文档根节点出发,随着DOM结构向事件的目标节点寻找。途中经过各个层次的DOM node,并在各node上触发捕获事件,直到到达时间的目标node。
目标阶段——终于等到你,还好我没放弃:
事件到达目标node,在目标node上被触发。
冒泡阶段——山谷回音:
事件在目标node上触发后,将由DOM树一层层向上冒泡,依次触发,直到到达最外层的根节点。这是时间委托所利用的特点。
请原谅我用这么文艺的方式给大家讲述事件触发的故事。O(∩_∩)O
懂得了事件冒泡的过程,就很容易明白事件委托的运作原理。当列表项的事件冒泡到父元素(即列表元素)时,可以查看事件对象的target属性,catch真正被点击的节点元素。下面是一段简单代码展示了这个过程:
document.getElementById("list").addEventListener("click",function(e) {
if(e.target && e.target.nodeName == "LI") {
//TO DO SOMETHING
}
});
解释一下代码: 获得父级元素list,为其绑定点击事件:如果子元素(列表项)被点击,当事件冒泡到list时,判断目标节点(事件来源)是否为li元素,如果是则触发该事件。
日常的例子: 假如你是一位小学班主任,你制定了一个规则:如果班里有人早恋就必须受到惩罚(定义了事件触发后执行的函数)。但是学生的活动范围是整个学校而不是局限于一个班,所以你就天天在学校里溜达(将事件绑定到父级元素)。突然看到有学生在接吻(事件句柄),你需要判断这个学生是不是自己班里的,如果是,请暴揍他一顿(触发事件,他还是个孩子,请不要放过他)。
当然,在真正的实际应用中也许没有这么简单,你也许只需要其中部分子元素绑定事件;也许还要考虑浏览器兼容的问题(在IE里目标元素放在srcElement属性中而不是target中,所以最好把获得目标元素写成一个跨浏览器的函数)。不过无论如何,你不需要为不确定的DOM而经常改变你的绑定,更不会因为过多的绑定导致性能的降低,大大降低崩溃的风险。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。