事件在 javascript 中一直是最强大的对象之一。javascript 提供了 addEventListener 和 attachEvent 两个方法来为 DOM 节点绑定事件,jquery 作了进一步封装,提供了兼容各个浏览器的 bind 方法。现在来看,这种传统的事件绑定方式存在着以下不足:
1. 可能需要绑定很多的 EventHander。
假如页面中某个表有 100 行,现在必须为每一行绑定一个 click 事件。那么就必须绑定 100 个 EventHandler,这对页面性能来说有着极大的负担,因为需要创建更多的内存来存放这些 Handler。
2. 事件无法绑定后加入的 DOM 节点。
假如页面中的代码如下:
后加入的 div 是无法触发点击事件的。
- $("#dv").bind('click',
- function() {
- alert('test');
- });
- $(body).append('<div id="dv">test</div>')
为了解决这两个问题,javascript 引入了事件代理(event proxy)。首先,我们了解一下 js 中的冒泡机制。
基本上所有的浏览器都支持事件冒泡。当在某个 DOM 节点上触发事件上,事件会一直向上传递,一直到文档的根节点。既然所有的节点的事件最终都会传递到文档根节点,那么我们如果直接将事件绑定到文档根节点(document 节点),然后通过 event.target 来判断是哪个节点触发的事件,是不是减少很多 EventHandler 的绑定呢?
jquery 中的 live 方法正式根据这个原理来实现的,下面我们来实现一个 live 简单版:
$.fn.mylive=function(eventType,fn){ var that=this.selector; $(document).bind(eventType,function(event){ var match=$(event.target).closest(that) if(match.length !== 0){ fn.apply($(event.target),[event]); } }) }
$("#tb td").mylive('click',function(event){alert(event.target.innerhtml);});
var tb=' \
live 方法弥补了前面提到的传统事件绑定方法的两个不足。但 live 方法仍存在它的不足之处。看这句代码:
$("#tb td").mylive('click',function(event){ alert(event.target.innerHTML); });它会首先根据 jquery 选择器遍历整个文档,找到所有的 #tb td 元素,将他们存储成对象。然而,在 live 的实现方法中,并没有利用这些对象,而仅仅是将 "#td td" 作为字符串与事件源进行匹配而已。这就大大增加了很多无谓的消耗。
那么有没有办法改善这一状况呢?jquery 中提供了 delegate 代理方法,它支持将事件绑定到指定的元素上,而不仅仅是 document 上。了解了它的原理,我们来实现一个 delegate 简单版:
$(body).append('<div id="dv"></div>');
$.fn.mydelegate=function(selector,eventType,fn){$(this).bind(eventType,function(event){var match=$(event.target).closest(selector); if(match.length !== 0){fn.apply($(event.target),[event]); } });}
$("#dv").mydelegate('td','click',function(event){alert(event.target.innerHTML);});
var tb=' \
mydeletage 方法不需要获取所有的 td 对象,而仅仅只需要获取绑定事件的 div 对象。这在执行效率上要优于 live 方法。
这里仅仅起到一个抛砖引玉的作用,让大家了解到事件代理的原理而已,jquery 中的 live 和 delegate 实现要复杂的多。
来源: http://www.phperz.com/article/17/0419/276689.html