2011年12月10日 星期六

了解 jQuery .bind .live .delegate 的差異



一般在使用事件綁定的時候我們會使用 .bind .live .delegate,在某些案例上使用感覺不出差別。但實際上這三個方式是不同的,下面我舉例說明一下有甚麼不同,最後做一個結論分享一下校能與使用情境的感想。

案例說明
我們需要 handle 整個 #container 中所有 a tag 的 click event,下面有三種寫法分別使用了 .bind .live .delegate。


HTML Example


<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta http-equiv="Content-Style-Type" content="text/css"> <title>what's different?</title> <script language="javascript" src="http://code.jquery.com/jquery-1.7.1.min.js"></script> </head> <body> <div id="container"> <a id="a1" href="#">link1</a> <a id="a2" href="#">link2</a> <a id="a3" href="#">link3</a> </div> </body> </html>

.bind
$("#container a").bind("click", function(){alert("what's different?");}); $("#container").append("<a id='add' href='#'>link spec</a>");

每次新增一個 Dom element 後需要重新 bind 才能夠讓該 Dom element 擁有 click 的 handle能力。
所以當執行了上面的 script 後,jQuery 會立即尋訪所有符合條件的 Dom element 並且 bind 上 click event handler。

.live
$("#container a").live("click", function(){alert("what's different?");}); $("#container").append("<a id='add' href='#'>link spec</a>");


在 event bubbling 發生的時候去做參數比對,bubbling 是當事件發生的時候會由 root 發出然後送到每個 children element,每個 children element 會決定是否該對這個做回應。
所以當你觸發了一次 live method 後,往後加入到 #container 的 Dom element 只要符合條件的都會在 event bubbling 的時候被觸發。

.delegate
$("#container").delegate("a", "click", function(){alert("what's different?");}); $("#container").append("<a id='add' href='#'>link spec</a>");

這個方法跟 live 不同的地方是除了 live 的條件之外,他會比對父物件也就是 delegate 某一個 Dom element。他會比對 parent dom element + css selector + event type 三個條件成立才會觸發。

效能問題

.bind .live .delegate 因為方式不同所以在效能上也不同。 

.bind 是在 script 執行後就執行完 event bind的動作,因此效能最好。
.live 會在 event bubbling 的時候對每個 dom element 做條件比對
.delegate 跟 live 的原理相同,但是會額外多比對 parent element 所以效能會比 live 好。

結論
live 可以一次控制所有元件並且不需要在意 dom element 新增的時間,但是會犧牲效能。.bind 會針對指定的 dom element 做處理,只會處理一次,因此指定範圍明確,所以效能最好。 .delegate 改善了 live 的缺點,可以將檢查範圍規範在特定的範圍內。不過每個開發的 usecase 不同,每個情況也不同,至於要使用怎樣的方法沒有絕對值,只能依照情況來做取捨,犧牲效能換取彈性? 這自己搞定吧!


沒有留言:

張貼留言