1. 程式人生 > >jQuery中的.bind()、.live()和.delegate()之間區別分析

jQuery中的.bind()、.live()和.delegate()之間區別分析

現在我們可以較容易地說明.bind()、.live()和.delegate()的不同之處了。
.bind()
程式碼如下: $('a').bind('click',function(){alert('That tickles!');})
這是最簡單的繫結方法了。JQuery掃描文件找出所有的$(‘a')元素,並把alert函式繫結到每個元素的click事件上。
.live()
 程式碼如下: $('a').live('click',function(){alert('That tickles!')})
JQuery把alert函式繫結到$(document)元素上,並使用'click'和'a'作為引數。任何時候只要有事件冒泡到document節點上,它就檢視該事件是否是一個click事件,以及該事件的目標元素與'a'這一CSS選擇器是否匹配,如果都是的話,則執行函式。
live方法還可以被繫結到具體的元素(或“context”)而不是document上,像這樣:
程式碼如下: $('a',$('#container')[0]).live('click',function(){alert('That tickles!')})
.delegate() 程式碼如下: $('#container').delegate('a','click',function(){alert('That tickles!')})

JQuery掃描文件查詢$('#container'),並使用click事件和'a'這一CSS選擇器作為引數把alert函式繫結到$('#container')上。任何時候只要有事件冒泡到$('#container')上,它就檢視該事件是否是click事件,以及該事件的目標元素是否與CSS選擇器相匹配。如果兩種檢查的結果都為真的話,它就執行函式。
可以注意到,這一過程與.live()類似,但是其把處理程式繫結到具體的元素而非document這一根上。精明的JS'er們可能會做出這樣的結論,即$('a').live() == $(document).delegate('a'),是這樣嗎?嗯,不,不完全是。
為什麼.delegate()要比.live()好用
基於幾個原因,人們通常更願意選用jQuery的delegate方法而不是live方法。考慮下面的例子:
程式碼如下: $('a').live('click', function() { blah() });

$(document).delegate('a', 'click', function() { blah() });
後者實際上要快過前者,因為前者首先要掃描整個的文件查詢所有的$(‘a')元素,把它們存成jQuery物件。儘管live函式僅需要把'a'作為串引數傳遞以用做之後的判斷,但是$()函式並未“知道”被連結的方法將會是.live()。

而另一方面,delegate方法僅需要查詢並存儲$(document)元素。
一種尋求避開這一問題的方法是呼叫在$(document).ready()之外繫結的live,這樣它就會立即執行。在這種方式下,其會在DOM獲得填充之前執行,因此就不會查詢元素或是建立jQuery物件了。
靈活性和鏈能力
live函式也挺令人費解的。想想看,它被鏈到$(‘a')物件集上,但其實際上是在$(document)物件上發生作用。由於這個原因,它能夠試圖以一種嚇死人的方式來把方法鏈到自身上。實際上,我想說的是,以$.live(‘a',…)這一形式作為一種全域性性的jQuery方法,live方法會更具意義一些。 僅支援CSS選擇器 最後一點,live方法有一個非常大的缺點,那就是它僅能針對直接的CSS選擇器做操作,這使得它變得非常的不靈活。 欲瞭解更多關於CSS選擇器的缺點,請參閱Exploring jQuery .live() and .die()一文。 更新:感謝Hacker News上的pedalpete和後面評論中的Ellsass提醒我加入接下來的這一節內容。 為什麼選擇.live()或.delegate()而不是.bind()
畢竟,bind看起來似乎更加的明確和直接,難道不是嗎?嗯,有兩個原因讓我們更願意選擇delegate或live而不是bind: 1. 為了把處理程式附加到可能還未存在於DOM中的DOM元素之上。因為bind是直接把處理程式繫結到各個元素上,它不能把處理程式繫結到還未存在於頁面中的元素之上。 2. 如果你運行了$('a').bind(…),而後新的連結經由AJAX加入到了頁面中,則你的bind處理程式對於這些新加入的連結來說是無效的。而另一方面live和delegate則是被繫結到另一個祖先節點上,因此其對於任何目前或是將來存在於該祖先元素之內的元素都是有效的。 3. 或者為了把處理程式附加到單個元素上或是一小組元素之上,監聽後代元素上的事件而不是迴圈遍歷並把同一個函式逐個附加到DOM中的100個元素上。把處理程式附加到一個(或是一小組)祖先元素上而不是直接把處理程式附加到頁面中的所有元素上,這種做法帶來了效能上的好處。 停止傳播
最後一個我想做的提醒與事件傳播有關。通常情況下,我們可以通過使用這樣的事件方法來終止處理函式的執行:
程式碼如下:
$('a').bind('click',function(e){
e.preventDefault()
e.stopPropagation()}
)