事件委託詳解

2022-03-08 01:45:19 字數 4197 閱讀 4012

基本概念

事件委託,通俗地來講,就是把乙個元素響應事件(click、keydown......)的函式委託到另乙個元素;

一般來講,會把乙個或者一組元素的事件委託到它的父層或者更外層元素上,真正繫結事件的是外層元素,當事件響應到需要繫結的元素上時,會通過事件冒泡機制從而觸發它的外層元素的繫結事件上,然後在外層元素上去執行函式。

舉個例子,比如乙個宿舍的同學同時快遞到了,一種方法就是他們都傻傻地乙個個去領取,還有一種方法就是把這件事情委託給宿舍長,讓乙個人出去拿好所有快遞,然後再根據收件人一一分發給每個宿舍同學;

在這裡,取快遞就是乙個事件,每個同學指的是需要響應事件的 dom 元素,而出去統一領取快遞的宿舍長就是**的元素,所以真正繫結事件的是這個元素,按照收件人分發快遞的過程就是在事件執行中,需要判斷當前響應的事件應該匹配到被**元素中的哪乙個或者哪幾個。

事件冒泡

前面提到 dom 中事件委託的實現是利用事件冒泡的機制,那麼事件冒泡是什麼呢?

在 document.addeventlistener 的時候我們可以設定事件模型:事件冒泡、事件捕獲,一般來說都是用事件冒泡的模型;

如上圖所示,事件模型是指分為三個階段:

委託的優點

1. 減少記憶體消耗

試想一下,若果我們有乙個列表,列表之中有大量的列表項,我們需要在點選列表項的時候響應乙個事件;

// ...... 代表中間還有未知數個 li
如果給每個列表項一一都繫結乙個函式,那對於記憶體消耗是非常大的,效率上需要消耗很多效能;

因此,比較好的方法就是把這個點選事件繫結到他的父層,也就是 `ul` 上,然後在執行事件的時候再去匹配判斷目標元素;

所以事件委託可以減少大量的記憶體消耗,節約效率。

2. 動態繫結事件

比如上述的例子中列表項就幾個,我們給每個列表項都繫結了事件;

在很多時候,我們需要通過 ajax 或者使用者操作動態的增加或者去除列表項元素,那麼在每一次改變的時候都需要重新給新增的元素繫結事件,給即將刪去的元素解綁事件;

如果用了事件委託就沒有這種麻煩了,因為事件是繫結在父層的,和目標元素的增減是沒有關係的,執行到目標元素是在真正響應執行事件函式的過程中去匹配的;

所以使用事件在動態繫結事件的情況下是可以減少很多重複工作的。

jquery 中的事件委託相信很多人都用過,它主要這幾種方法來實現:

基本實現

比如我們有這樣的乙個 html 片段:

item 1li>

item 2li>

item 3li>

......

item nli>

ul>

// ...... 代表中間還有未知數個 li

我們來實現把 #list 下的 li 元素的事件**委託到它的父層元素也就是 #list 上:

// 給父層元素繫結事件

document.getelementbyid('list').addeventlistener('click', function (e)

});

在上述**中, target 元素則是在 #list 元素之下具體被點選的元素,然後通過判斷 target 的一些屬性(比如:nodename,id 等等)可以更精確地匹配到某一類 #list li 元素之上;

使用 element.matches 精確匹配

如果改變下 html 成:

item 1li>

item 2li>

item 3li>

......

item nli>

ul>

// ...... 代表中間還有未知數個 li

這裡,我們想把 #list 元素下的 li 元素(並且它的 class 為 class-1)的點選事件委託**到 #list 之上;

如果通過上述的方法我們還需要在 `if (target.nodename.tolocalelowercase === 'li')` 判斷之中在加入乙個判斷 `target.nodename.classname === 'class-1'`;

但是如果想像 css 選擇其般做更加靈活的匹配的話,上面的判斷未免就太多了,並且很難做到靈活性,這裡可以使用 element.matches api 來匹配;

element.matches api 的基本使用方法: element.matches(selectorstring),selectorstring 既是 css 那樣的選擇器規則,比如本例中可以使用 target.matches('li.class-1'),他會返回乙個布林值,如果 target 元素是標籤 li 並且它的類是 class-1 ,那麼就會返回 true,否則返回 false;

當然它的相容性還有一些問題,需要 ie9 及以上的現代化瀏覽器版本;

我們可以使用 polyfill 來解決相容性上的問題:

if (!element.prototype.matches) 

return i > -1; };}

加上 element.matches 之後就可以來實現我們的需求了:

if (!element.prototype.matches) 

return i > -1;

};}document.getelementbyid('list').addeventlistener('click', function (e)

});

這裡就有幾個關鍵點:

function eventdelegate (parentselector, targetselector, events, foo) 

return i > -1; };}

// 判斷是否匹配到我們所需要的元素上

if (target.matches(targetselector))

} // 如果有多個事件的話需要全部一一繫結事件

events.split('.').foreach(function (evt) );

});}

js事件委託詳解

首先說一下事件冒泡和事件捕獲機制,事件冒泡是有微軟公司提出來的,事件捕獲是有網景公司提出來的,當時兩家是爭論的不可開交,後來w3c也沒辦法,就採取了折中的方式,事件產生後先捕獲後冒泡,通常,在js中監聽事件的方法共有三種,分別是 ele.addeventlistener type,listener,...

委託和事件 三 事件詳解

談到事件,不得不牽扯到兩個角色 事件發行者 publisher 乙個事件的發行者,也稱作是傳送者 sender 其實就是個物件,這個物件會自行維護本身的狀態資訊,當本身狀態資訊變動時,便觸發乙個事件,並通知說有的事件訂閱者。事件訂閱者 subscriber 對事件感興趣的物件,也稱為receiver...

C 委託和事件詳解

委託delegate delegate是c 中的一種型別,它實際上是乙個能夠持有對某個方法的引用的類。與其它的類不同,delegate類能夠擁有乙個簽名 signature 並且它 只能持有與它的簽名相匹配的方法的引用 它所實現的功能與c c 中的函式指標十分相似。它允許你傳遞乙個類a的方法m給另乙...