.bind(), .live(), 和 .delegate()之間的區別並不明顯。可是理解它們的不一樣之處有助於寫出更簡潔的代碼,並防止咱們的交互程序中出現沒有預料到的bug。css
基礎jquery
DOM樹ajax
首先,圖形化的HTML文檔能幫助咱們更好的理解。一個簡單的HTML頁面看起來應該像這樣api
事件冒泡(也稱做事件傳遞)(Event bubbling aka event propagation)函數
點擊一個連接,觸發綁定在連接元素上的 click 事件,進而觸發綁定到這個元素的click事件的函數。性能
1spa |
$('a').bind('click', function() { alert("That tickles!") });對象 |
因此一次點擊會觸發一個alert。
而後,這個 click 事件會從DOM樹向上傳遞,傳播到父元素,而後傳遞給每個祖先元素。blog
在DOM樹中, document 是根節點。
如今咱們能容易的解釋.bind(), .live(), 和 .delegate()之間的差異了事件
.bind()
1 |
$('a').bind('click', function() { alert("That tickles!") }); |
這是最直接的綁定方法。jQuery 掃描文檔找到全部 $(‘a’) 元素,而後給每個找到的元素的 click 事件綁定處理函數。
.live()
1 |
$('a').live('click', function() { alert("That tickles!") }); |
jQuery綁定處理函數到 $(document) 元素,並把 ‘click’ 和 ‘a’ 做爲函數的參數。有事件冒泡到document節點的時候,檢查這個事件是否是 click 事件,target element能不能匹配 ‘a’ css選擇器,若是兩個條件都是true,處理函數執行。
live方法也能夠綁定到指定的元素(或者說「上下文(context)」)而不用綁定到document,好比:
1 |
$('a', $('#container')[0]).live(...); |
.delegate()
1 |
$('#container').delegate('a', 'click', function() { alert("That tickles!") }); |
jQuery掃描文檔找到 $(‘#container’),綁定處理函數到他的 click 事件,’a’ css選擇器做爲函數的參數。當有事件冒泡到 $(‘#container’),檢查事件是否是 click,並檢查target element是否是匹配css選擇器,若是二者都符合,執行函數。
注意此次和 .live() 方法很類似,除了把事件綁定到特定元素與跟元素的區別。精明的JS’er 或許會總結成 $(‘a’).live() == $(document).delegate(‘a’),真的是這樣嗎? 不,不全是。
爲何 .delegate() 比 .live() 好
jQuery 的 delegate方法比 live 方法更應該成爲首選有一個緣由。考慮如下的場景:
1 2 3 |
$('a').live('click', function() { blah() }); // or $(document).delegate('a', 'click', function() { blah() }); |
速度
上面第二個執行比第一個快,由於第一個會遍歷整個文檔查找 $(‘a’) 元素,並保存爲jQuery對象,可是live方法只須要傳一個字符串參數’a'而已,$() 方法並不知道咱們會用鏈式表達式在後面用上.live()。
delegate 方法就只須要找到並存貯 $(document)元素就夠了。
有一種hack是在 $(document).ready()以外調用live方法,這樣就會當即執行。這時候DOM尚未填充,也就不會查找元素或建立jQuery對象。
靈活性和鏈式語法
這方面live方法依然使人費解。想一下,它鏈在$(‘a’)對象,但其實是在$(document)對象起做用。由於這個緣由,在鏈式表達式中使用live讓人很不安,我以爲live方法變成一個全局的jQuery方法 $.live(‘a’,…) 會更有意義。
只支持css選擇器
最後,live方法有一個最大的缺點,只能用css選擇器,用起來很不方便。
有關css選擇器的缺點,參看 Exploring jQuery .live() and .die()。
原做者更新
爲何使用 .live() 或 .delegate() 而不用 .bind()
最後,bind 方法看起來更清晰,更直接,是嗎?可是這裏有兩個緣由咱們推薦 delegate 或 live:
阻止冒泡
最後注意一下事件冒泡。一般咱們能用這樣的方法阻止其餘處理函數:
1 2 3 4 5 |
$('a').bind('click', function(){ e.preventDefault(); //or e.stopPropagation(); }) |
可是在這裏,用 live 或 delegate 方法綁定的事件會一直傳遞到事件真正綁定的地方纔會執行。這時其餘的函數已經執行過了。