事件委托其实并不是一个很高级的技巧,比如在一个页面里面,当只存在两个按钮的时候,可能你给按钮添加监听是这样的:(本文不考虑浏览器兼容性,关于事件的兼容性可参考前面的学习笔记)
<div id="container">
<button id="btn1">按钮1</button>
<button id="btn2">按钮2</button>
</div>
var btn1 = document.getElementById("btn1");
var btn2 = document.getElementById("btn2");
btn1.addEventListener("click", clickHandler1);
btn2.addEventListener("click", clickHandler2);
当按钮越来越多的时候,甚至到了几十上百的时候,我相信很少有人会选择一个一个的添加事件,首先,其实事件处理函数每个都是对象,都会占用内存,创建的越多,内存开销越大,性能越差;其次,大量“重复”性的代码拥挤在脚本里,非常难以维护,也非常难看;还有,添加大量监听意味着要频繁访问DOM元素,延迟整个页面的访问时间。
事件委托就是解决这个问题的一个方案。我们知道,在DOM节点构成的DOM树中,子节点产生一个事件之后会逐级冒泡到父元素上:
事件委托就利用这一特性,只需给所有的按钮的父元素比如container添加一个事件,这样无论是哪个按钮,只要触发了绑定的事件都会冒泡到container上,我们只需判断是不是你想监听的按钮即可。
var container = document.getElementById("container");
container.addEventListener("click", function(e){
//获取事件触发对象
var target = e.target;
if(target.id == "btn1"){
alert("btn1");
}else if(target.id == "btn2"){
alert("btn2");
}
});
这个方法还有一个明显的好处是你不必再问以后创建的元素添加监听。比如在上面的判断里添加
else if(target.id == "btn3"){
alert("btn3");
}
添加这个事件处理程序的时候页面中还并没有btn3,但btn3很可能是由用户动态创建的,但不管用户什么时候创建,你都能在这个条件里捕获它。
JQuery里面的事件委托
其实在JQuery里,因为很容易创建一个JQuery集合,所以处理事件相对简单。
一、click函数、bind函数等:
$("a").click(function(){
if($(this).hasClass("a1")){
//...
}else if(...){
//...
}
});
$("a").bind("click", function(){
if($(this).hasClass("a1")){
//...
}else if(...){
//...
}
});
其实这个方法同样也是通过遍历所有a标签,给他们添加事件函数,但比原生js代码量要少很多。
二、live()
live和上面讲的原生js类似,不指定父元素的时候,将事件绑定在了document上,比如:
$(".link").live("click", function(){
//...
});
当有事件冒泡到document上时,将检查事件是否为click事件,元素是否带有link的className,满足这两个条件则将触发事件处理函数。
除了默认绑定在document上,也可以绑定在指定父元素上:
$(".link", $("#container")).live("click", function(){
//...
});
三、delegate
其实不管是live还是bind,他们的写法都很奇怪,我们讨论的事件委托都是给父元素添加的事件监听,但一直到现在都好像是在子元素上调用的方法,不过还好JQuery里面还有一个函数:delegate。
同样是绑定事件到.link筛选条件上,使用delegate方法如下:
$("#container").delegate(".link", "click", function(){
//...
});
可以看到,我们在需要绑定的父元素(id名为container的元素)上调用的delegate方法,并传递三个参数:监听元素筛选条件、监听事件名、事件处理函数。
通过链式调用更加舒服:
$("#container").delegate(".link", "click", function(){
//...
}).delegate(".btn", "click", function(){
//...
}).delegate(".whatever", "click", function(){
//...
});
注意
bind是不能为后面动态生成的元素绑定事件的(因为调用bind时遍历的是当时页面里的所有元素)。
live和delegate是可以为动态生成的元素触发事件处理函数的,因为绑定在父元素上的只是一个筛选条件。
最后需要注意的是同样是绑定在document元素上的click事件:
$(".btn").live("click", function(){
//...
});
$("document").delegate(".btn", "click", function(){
//...
});
最好使用delegate方法,因为虽然live同样是绑定在document上,但$(“.btn”)这句代码还是会遍历所有的.btn元素并给其创建JQuery对象,相比于直接使用document,性能上会有所不如。
当然,就拿写法来说,我们也更应该喜欢delegate方法。
版权声明:本文为博主原创文章,未经博主允许不得转载。