.bind().live(), 和 .delegate()这三个方法的区别并不是非常明显。弄清楚这些区别对我们写出简介的代码和预防我们的应用中出现bugs是非常有帮助的。

jQuery团队在1.7版本中发布了一个用于绑定事件的新方法叫做on。这个方法包含了下面所介绍的live, bind, 和 delegate的功能,允许我们通过传递不同的参数指定绑定事件的方式而不是通过不同的方法名。

基础知识

DOM树

首先,DOM树形象的描述了一个HTML文档的DOM结构。下图是一个简单HTML页面的DOM树:

Event bubbling (aka event propagation)

事件冒泡(事件传递)

当我们点击一个链接,链接元素会发出一个click事件,这个事件会触发那些与该元素click事件绑定的方法。

$('a').bind('click', function() { alert("That tickles!") });

如上这段代码,链接点击时会触发一个alert。

click事件会沿着树向上传递广播到父元素,所有子元素上触发的事件都会沿树向上传递直到根元素。

在HTML的DOM操作中,document是跟节点。

下面我们来看.bind(),.live(), 和 .delegate()之间的区别。

.bind()
$('a').bind('click', function() { alert("That tickles!") });

这个是绑定事件处理方法最直接的途径。jQuery遍历document中所有 $('a')元素并将每个元素的click事件绑定alert方法。

.live()
$('a').live('click', function() { alert("That tickles!") });

jQuery在 $(document)元素上绑定alert方法,同时将‘click’和‘a’作为参数。当一个事件传递到document节点时,节点会检验事件类型是否为click同时检验事件的目标元素类型是否同选择符‘a’相匹配。如果检验通过那么执行alert方法。

除了document,live方法还可以将方法绑定到指定的元素上,如下:

$('a', $('#container')[0]).live(...);
.delegate()
$('#container').delegate('a', 'click', function() { alert("That tickles!") });

jQuery遍历document检索出 $('#container')元素并绑定alert方法同时将click事件和'a'选择符作为参数。当一个事件传递到 $('#container')时,它检验事件类型是否为click并且目标元素同'a'选择符相符。如果通过检验则执行方法。

这里需要注意这个方法同.live()有些相似,他们的不同之处在于.delegate()方法将方法绑定到特定的元素而.live()绑定到document根元素。也许我们会问 是不是$('a').live() == $(document).delegate('a')?? 答案是否,并不完全相同。

为什么.delegate()比.live()更推荐使用

jQuery的delegate方法同live方法相比有如下几点优势。

$('a').live('click', function() { blah() });
// or
$(document).delegate('a', 'click', function() { blah() });
速度

如上两种绑定事件的方法效果是相同的。但是第二种方法在执行速度上要快于第一种。因为第一种方法需要从document节点开始检索出所有$(‘a’)元素,并将这些元素保存为jQuery对象。尽管live方法仅需要使用传递的选择符’a'就可以检验出哪些事件需要处理,但是$()方法并不知道它后面所接的方法是.live().

而delegate方法仅查找并保存$(document)元素。

灵活性和代码连续性

live相比起来更复杂。因为虽然它接在$(‘a’)对象之后,但是它实际上是在 $(document)对象上工作。正因为此,它后面所接的方法会难以理解。实际应用中更推荐使用$.live('a',...)以绑定到指定元素上。

只能用CSS选择符

live方法最大的缺点就是它只能直接使用CSS选择符来进行操作,这使得这个方法在使用中非常的不灵活。

关于CSS选择符的缺点参考 Exploring jQuery .live() and .die().

为何推荐使用.live()或.delegate()代替.bind()

从上述来看似乎bind方法使用更清晰更直接,但是考虑以下两点我们更倾向使用live和delegate方法:

  • 为还不存在的DOM元素绑定事件方法。因为bind直接将方法绑定到独立的元素上,它不能将方法绑定到一个在页面上不存在的元素。因此如果我们执行$(‘a’).bind(…),那些通过AJAX后添加到页面上的链接则不会被绑定。而live和delegate方法是将事件方法绑定到一个指定父节点上,那么这个节点下已经存在的元素或后添加的元素的事件都可以被处理。
  • 通过为单独元素或一组元素绑定方法监听所有它们的子元素,而不需要通过循环为每个独立的DOM元素绑定相同的方法。将一个方法绑定到一个或一组父元素比直接为页面上的每个元素都绑定方法运行效率要高很多。

终止事件传递

最后关于终止事件传递有一点需要提醒,通常我们可以通过终止事件传递来避免其他事件处理方法的运行:

$('a').bind('click', function(e) {
	e.preventDefault();
	// or
	e.stopPropagation();
});

但是,当我们使用live或delegte方法时,事件处理方法直到事件传递到所绑定的元素时才会真正运行,这时通过.bind()绑定的事件方法其实已经运行了。

转自 http://www.sjslibrary.com/?p=332

喜欢这篇文章吗,不妨分享给朋友们吧!