JQ 為未來元素新增事件處理器 事件委託

2022-07-05 07:06:14 字數 3258 閱讀 4804

隨著dom結構的複雜化和ajax等動態指令碼技術的運用,有了較多的動態新增進來的元素,直接用jq新增click事件會發現新新增進來的元素並不能直接選取到,在這裡就需要用到事件委託方法,jq為事件委託提供了live()、dalegate()和on()方法。   

我們知道,dom在為頁面中的每個元素分派事件時,相應的元素一般都在事件冒泡階段處理事件。在類似 body > div > a 這樣的結構中,如果單擊a元素,click事件會從a一直冒泡到div和body(即document物件)。因此,發生在a上面的單擊事件,div和body元素同樣可以處理。而利用事件傳播(這裡是冒泡)這個機制,就可以實現事件委託。具體來說,事件委託就是事件目標自身不處理事件,而是把處理任務委託給其父元素或者祖先元素,甚至根元素(document)。

.live()

jquery 1.3新增的live()方法,用法如下:

$("#info_table td").live("click",function());
這裡的.live()方法會把click事件繫結到$(document)物件,而且只需要給$(document)繫結一次,然後就能夠處理後續動態載入的單元格的單擊事件。在接收到任何事件時,$(document)物件都會檢查事件型別和事件目標,如果是click事件且事件目標是td,那麼就執行委託給它的處理程式。

到目前為止,一切似乎很完美。可惜,事實並非如此。因為.live()方法並不完美,它有如下幾個主要缺點:

為了避免生成不必要的jquery物件,可以使用一種叫做「早委託」的hack,即在$(document).ready()方法外部呼叫.live():

(function

($));

})(jquery);

在此,(function($))(jquery)是乙個「立即執行的匿名函式」,構成了乙個閉包,可以防止命名衝突。在匿名函式內部,$引數引用jquery物件。這個匿名函式不會等到dom就緒就會執行。注意,使用這個hack時,指令碼必須是在頁面的head元素中鏈結和(或)執行的。之所以選擇這個時機,因為這時候剛好document元素可用,而整個dom還遠未生成;如果把指令碼放在結束的body標籤前面,就沒有意義了,因為那時候dom已經完全可用了。

為了避免事件冒泡造成的效能損失,jquery從1.4開始支援在使用.live()方法時配合使用乙個上下文引數:

$("td",$("#info_table")[0]).live("click",function());
這樣,「受託方」就從預設的$(document)變成了$("#infotable")[0],節省了冒泡的旅程。不過,與.live()共同使用的上下文引數必須是乙個單獨的dom元素,所以這裡指定上下文物件時使用的是$("#infotable")[0],即使用陣列的索引操作符來取得的乙個dom元素。

如前所述,為了突破單一.bind()方法的侷限性,實現事件委託,jquery 1.3引入了.live()方法。後來,為解決「事件傳播鏈」過長的問題,jquery 1.4又支援為.live()方法指定上下文物件。而為了解決無謂生成元素集合的問題,jquery 1.4.2乾脆直接引入了乙個新方法.delegate()。

使用.delegate(),前面的例子可以這樣寫:

$("#info_table").delegate("td","click",function());
使用.delegate()有如下優點(或者說解決了.live()方法的如下問題):

可見,.delegate()方法是乙個相對完美的解決方案。但在dom結構簡單的情況下,也可以使用.live()。

在下列情況下,應該使用.live()或.delegate(),而不能使用.bind():

.on()

根據jquery 1.7 beta 1的發版說明,jquery 1.7為了解決.bind()、.live()和.delegate()並存造成的不一致性問題,將會增加一對新的事件方法:.on()和.off(),以下為on()的實現方式:

.on( events [, selector ] [, data ], handler(eventobject) )
乙個簡單的事件繫結如 $('button').on('click',function(){}); 與bind()無二樣。

在需要為較多的元素繫結事件的時候,優先考慮事件委託,可以帶來效能上的好處。比如:

如上圖,將click事件繫結在document物件上,頁面上任何元素發生的click事件都冒泡到document物件上得到處理。

注意到.on()的描述中第二個可選引數:selector。如下圖,新增了第二個引數,選擇符button:

結果:當事件冒泡到document物件時,檢測事件的target,如果與傳入的選擇符(這裡是button)匹配,就觸發事件,否則不觸發。 

注意.on()也可以接收乙個物件引數,該物件的屬性是事件型別,屬性值為事件處理函式。下面是官方文件的乙個例子:

最後有一點,原先的live()方法,處理函式是預設繫結在document物件上不能變的,如果dom巢狀結構很深,事件冒泡通過大量祖先元素會導致較大的效能損失。而使用.on()方法,事件只會繫結到$()函式的選擇符表示式匹配的元素上(上面我的例子中,為了簡單繫結到了document),因此可以精確地定位到頁面中的一部分,而事件冒泡的開銷也可以減少。delegate()與on()同理,畢竟是用on()實現的:

.on()和.off():實現方式

$(elems).on(events, selector, data, fn);

$(elems).off(events, selector, fn);

如果指定selector,則為事件委託;否則,就是常規繫結。新舊api對應如下:

Jquery為動態新增的未來元素繫結事件

語法 selector on event,childselector,data,function event 必需。規定要從被選元素移除的乙個或多個事件或命名空間。由空格分隔多個事件值,也可以是陣列。必須是有效的事件。childselector 可選。規定只能新增到指定的子元素上的事件處理程式 且不...

jq中如何對未來元素繫結事件

對未來元素繫結,不可以用bink,雖然可以用live代替但是jquery的版本,根據官方文件,從1.7開始就不推薦live和delegate了,1.9裡就去掉live了。下面就是簡單的一串 用on 來對未來元素進行繫結 lang en charset utf 8 name viewport cont...

js 實現給未來元素新增事件。

未來元素 不是乙個頁面上的元素,是通過js或者通過後台直接渲染在頁面上的元素,也就是說這些元素不是直接寫在document中的。1.對於未來元素,我們想直接用js或者jq操作它們是不起作用的。1 element on click function 2.可以使用來操作未來生成的元素,可是這裡有乙個侷限...