jQuery中的.bind()、.live()和.delegate()之間區別分析,學習jquery的朋友可以參考下。
DOM樹
#首先,視覺化一個HMTL文件的DOM樹是很有幫助的。一個簡單的HTML頁面看起來就像是這個樣子:
#事件冒泡(又稱事件傳播)
當我們點擊一個連結時,其觸發了連結元素的點擊事件,該事件則引發任何我們已綁定到該元素的點擊事件上的函數的執行。
程式碼如下:
$('a').bind('click',function(){alert('that tickles!')})
#因此一個點選操作會觸發alert函數的執行。
click事件接著會向樹的根方向傳播,廣播到父元素,然後接著是每個祖先元素,只要是它的某個後代元素上的單擊事件被觸發,事件就會傳給它。
在操縱DOM的脈絡中,document是根節點。
現在我們可以輕易地說明.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()} )
不過,當我們使用live或是delegate方法的時候,處理函數其實並沒有在執行,需要等到事件冒泡到處理程序實際綁定的元素上時函數才會運作。而到此時為止,我們的其他的來自.bind()的處理函數早已運行了。
以上是jQuery中的.bind()、.live()和.delegate()之間區別分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!