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

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()的處理函數早已運行了。
相關文章
相關標籤/搜索