jQuery .delegate() vs .live()
.live()與.delegate()都是藉重DOM事件會由子元素一路向父元素Bubble Up的特性,在document或特定元素統一掛上事件函數,事件被觸發時再透過選擇器比對事件目標元素是否吻合,決定要不要執行事件邏輯,藉此提升效率,同時還能將"未來才會建立的元素"也納入事件的涵蓋範圍。(細節可參考舊文)
不過,.live()與.delegate()做的事幾乎一模一樣,依江湖上的說法,1.4版推出的.delegate()又比1.3版誕生的.live()來得有效率,理由何在?
以對<table id="t">下所有<td>加掛click事件為例,多半會寫成:
$("#t td").live("click", fn); 或 $("#t").delegate("td", "click", fn);
當執行$("#t td").live(),jQuery會監聽document的click事件,再依event.target是否吻合選擇器"#t td"決定live()所指定的click事件要不要被觸發;若使用$("#t").delegate(),jQuery監聽click事件的對象則會由document換成<table id="t">,但也一樣是比對event.target是否為td決定要不要觸發事件。二者相比,將監聽對象由document縮小到table對效能有利! 因為$("#t td").live()會過濾比對document上所有子元素產生的click事件,而$("#t").delegate("td"…)只有在table內子元素被click時才進行比對過濾,避免了非目標區元素被click時的多餘過濾流程。不過,這部分的效能損耗其實可以避免,只要改寫成$("td", document.getElementById("t")),則.live()的監聽對象就會被縮小到table而非document,此一差異性就消失了。但是,真要比效能,.live()還是難逃敗陣的命運! 為什麼?
對.live()或.delegate()來說,"td"是未來click事件觸發時比對event.target用的選擇器,理論上保留字串就夠了。當寫成$("td", document.getElementById("t")),jQuery會找尋當下所有符合的td元素,建出jQuery集合物件,但這個耗費資源建立的物件卻沒有發揮任何作用,而這個無謂的物件建立過程,在td的數量很多的情境下,就足以產生明顯效能差異。
我設計了一個實驗來驗證:如上圖,Test .live()及Test .delegate()可攔載所有<td>的click事件,分別將<td>的文字內容顯示在第一列右側的兩個<span>中,而按下Create Table則會建出5萬個<td>。
第一個測試我們可以先按Test .live(),再按Test .delegate(),應該都是0 ticks完成,之後按Create Table建立<td>,點選<td>就可以驗證.live()、delegate()均成功攔截到click事件。
第二個測試,則是先按Create Table建立出5萬個<td>,再按Test .live()及Test .delegate(),在我的電腦上,按Test .delegate()仍是瞬間完成,按Test .live()卻要耗上35+ ticks,推測應就是前述建立5萬個<td>元素jQuery集合耗費的時間。
最後再補充一點,如果程式思維是針對某個元素進行一連串動作: 先針對其下的子元素掛上事件,然後再進行其他操作,.delegate()允許我們寫成$("#t").delegate("..", "click", fn).css("..", "..").attr("..", "..")的串接形式,符合jQuery的直覺寫法;而.live()由於需將子元素視為主體,就無法像.delegate()般一氣喝成,也算是.delegate()寫法的另一項優點。
轉自:http://blog.darkthread.net/post-2011-10-14-delegate-vs-live.aspx