js事件冒泡和事件委託

2022-02-09 04:02:49 字數 4357 閱讀 2617

js事件冒泡

js所謂的事件冒泡就是子級元素的某個事件被觸發,它的上級元素的該事件也被遞迴執行

html:

js:

$("ul[data-type='citypick']").on('click',function

());

$("ul[data-type='citypick']").on('click','li',function

());

當li的點選事件被觸發時,父級ul的點選事件也被觸發執行了,

而在某些場合我們是不希望它冒泡的,怎麼做呢? 簡單!

js:

$("ul[data-type='citypick']").on('click',function

());

$("ul[data-type='citypick']").on('click','li',function

(e));

加上e.stoppropagation(); 這一句便可以阻止事件冒泡了

js事件委託

js事件委託,其實是

使用了冒泡的原理,從點選的元素開始,遞迴方式的向父元素傳播事件,這樣做的好處是對於大量要處理的元素,不必為每個元素都繫結事件,只需要在他們的父元素上繫結一次即可,提高效能。 還有乙個好處就是可以處理動態插入dom中的元素,直接繫結的方式是不行的。

就是事件目標自身不處理事件,而是把處理任務委託給其父元素或者祖先元素,甚至根元素事件委託很好地利用了"事件冒泡"。當點選子元素,根據"事件冒泡",該子元素的父級元素捕獲了該次點選事件,並觸發自己的方法。

看例項:

假如現在有10個按鈕,要為每個按鈕繫結乙個click事件,可能才十個按鈕,你可以乙個乙個的繫結或用迴圈進行繫結,但是這樣效能呢?

html:

<

div

class

="button-group"

>

<

bottoun

type

="button"

class

="btn"

>提交

bottoun

>

<

bottoun

type

="button"

class

="btn"

>提交

bottoun

>

<

bottoun

type

="button"

class

="btn"

>提交

bottoun

>

<

bottoun

type

="button"

class

="btn"

>提交

bottoun

>

<

bottoun

type

="button"

class

="btn"

>提交

bottoun

>

<

bottoun

type

="button"

class

="btn"

>提交

bottoun

>

<

bottoun

type

="button"

class

="btn"

>提交

bottoun

>

<

bottoun

type

="button"

class

="btn"

>提交

bottoun

>

<

bottoun

type

="button"

class

="btn"

>提交

bottoun

>

<

bottoun

type

="button"

class

="btn"

>提交

bottoun

>

div>

js:

$(".button-group").on('click','.btn',function

());

這裡可以看出,我們只是為所有的button的乙個父級繫結了click事件,而不是為所有的button繫結事件,極大的提高了效能,這樣做的好處還有可以對動態加進來的元素進行處理

就是有乙個按鈕原本的dom裡面是沒有的,是你通過其他方式新增進來的,即未來元素,用直接繫結方法是不能成功的,只能用事件委託,委託給該元素的父級進行處理

由於事件委託是通過事件冒泡實現的,所以如果子級的元素阻止了事件冒泡,那麼事件委託也將失效!

其實jqueryjquery 1.7 beta 1之前版本為繫結和委託事件提供了.bind()、.live()和.delegate()方法,可以說是一步步改進,

.bind()

假設有乙個多行多列的**,我們想讓使用者單擊每個單元格都能看到與其中內容相關的更多資訊(比如,通過提示條)。為此,可以為每個單元格都繫結click事件:

$("info_table td").bind("click", function()); 

問題是,如果**中要繫結單擊事件的有10列500行,那麼查詢和遍歷5000個單元格會導致指令碼執行速度明顯變慢,而儲存5000個td元素和相應的事件處理程式也會占用大量記憶體

.live()

事件委託可以解決上述兩個問題。具體到**上,只要用jquery 1.3新增的.live()方法代替.bind()方法即可:

$("#info_table td").live("click",function());

這裡的.live()方法會把click事件繫結到$(document)物件(但這一點從**中體現不出來,這也是.live()方法飽受詬病的乙個重要原因,稍後再詳細討論),而且只需要給$(document)繫結一次(不是50次,更不是5000次)。在接收到任何事件時,$(document)物件都會檢查事件型別和事件目標,如果是click事件且事件目標是td,那麼就執行委託給它的處理程式。

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

$()函式會找到當前頁面中的所有td元素並建立jquery物件,但在確認事件目標時卻不用這個td元素集合,而是使用選擇符表示式與event.target或其祖先元素進行比較,因而生成這個jquery物件會造成不必要的開銷;

預設把事件繫結到$(document)元素,如果dom巢狀結構很深,事件冒泡通過大量祖先元素會導致效能損失;

只能放在直接選擇的元素後面,不能在連綴的dom遍歷方法後面使用,即$("#infotable td").live...可以,但$("#infotable").find("td").live...不行;

收集td元素並建立jquery物件,但實際操作的卻是$(document)物件,令人費解。

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

$("td",$("#info_table")[0]).live("click",function());

這樣,「受託方」就從預設的$(document)變成了$("#infotable")[0],節省了冒泡的旅程。

.delegate()

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

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

$("#info_table").delegate("td","click",function()); 

jquery 1.7為了解決.bind()、.live()和.delegate()並存造成的不一致性問題,將會增加一對新的事件方法:.on()和.off():

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

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

如果指定selector,則為事件委託;否則,就是常規繫結。

所以現在只要用on方法就可以了,推薦用on方法進行委託或常規繫結事件

JS事件冒泡 事件捕獲和事件委託

如上圖所示 事件冒泡 結構上從內到外 如上圖所示 事件捕獲 結構上從外到內 使用addeventlistener 方法指定事件是否在捕獲或冒泡階段執行 element.addeventlistener event,function,usecapture usecapture 可選。布林值,指定事件是...

事件冒泡和事件委託

今天學到了事件冒泡和事件委託這兩個詞,現在談一下我的理解。如果有錯誤,還望各位大佬及時糾正,謝謝。事件冒泡 父元素和子元素有觸發事件時,如果子元素觸發,會引起父元素事件也觸發。有一點搞清楚,父元素通常就相當於是乙個大盒子,而子元素則是裡面的內容。解決辦法 有時候,不需要觸發父元素的時候,可以使用ev...

事件冒泡 事件捕獲和事件委託

事件冒泡會從當前觸發的事件目標一級一級往上傳遞,依次觸發,直到document為止。事件捕獲會從document開始觸發,一級一級往下傳遞,依次觸發,直到真正事件目標為止。事件委託依靠的就是事件冒泡和事件捕獲的機制。box1 box2 box3 上面是三個具有父子關係的box,分別繫結了列印事件,現...