事件委托 1. 事件流 事件流描述的是從頁面中接收事件的順序。 JS高級程式設計(第3版) 規定的事件流有三個階段:①事件 捕獲 階段、②處於 目標 階段、③事件 冒泡 階段 2. 事件委托 當需要添加的事件過多時,可以使用 事件委托 ,而事件委托實際上利用了事件 冒泡 的特性。 使用事件委托還需了 ...
事件委托
事件流
事件流描述的是從頁面中接收事件的順序。---JS高級程式設計(第3版)
DOM Level 2 Events
規定的事件流有三個階段:①事件捕獲階段、②處於目標階段、③事件冒泡階段事件委托
當需要添加的事件過多時,可以使用事件委托,而事件委托實際上利用了事件冒泡的特性。
使用事件委托還需瞭解事件對象(
event
):在觸發DOM上的某個事件時,會產生一個事件對象event
,這個對象中包含著所有與事件有關的信息。在此僅需知道在
DOM
標準中,event
擁有一個target
屬性表示事件目標。event.target
是一個觸發事件的對象的引用。它與event.currentTarget
不同, 當事件處理程式在事件的冒泡或捕獲階段被調用時。(mdn)具體
Event
詳情可以查看MDN:Event
如果你想要在大量子元素中單擊任何一個都可以運行一段代碼,您可以將事件監聽器設置在其父節點上,並將事件監聽器氣泡的影響設置為每個子節點,而不是每個子節點單獨設置事件監聽器。(mdn)
以下麵的html代碼為例:
<ul id="list"> <li id="one">do something</li> <li id="two">do something</li> <li id="three">do something</li> </ul>
當需求是單擊上面每個
li
標簽都會執行各種操作時,使用事件委托是較好的選擇。// bad (逐個 li 添加事件) let item1 = document.getElementById('one'); let item2 = document.getElementById('two'); let item3 = document.getElementById('three'); item1.addEventListener('click', function(){...}, false); item1.addEventListener('click', function(){...}, false); item1.addEventListener('click', function(){...}, false); // event delegation (事件委托) let list = document.getElementById('list'); list.addEventListener('click', function(e){ if (e.target && e.target.nodeName == 'LI') { switch (e.target.id) { case 'one': do something; break; case 'two': do something; break; case 'three': do something; break; } } }, false);
註意:當
li
標簽被如p
、div
等撐滿時,點擊的target
為p
標簽而不是li
標簽會導致無法正確執行click
事件。以下麵的html代碼為例:
<ul id="list"> <li id="one">do something</li> <li id="two">do something</li> <!-- 這裡的 li 裡面有個 p 標簽 --> <li id="three"><p>do something</p></li> </ul>
這樣的情況可以使用遞歸 or 迴圈來處理,畢竟事件委托是利用事件冒泡的特性。
//遞歸 let list = document.getElementById('list'); list.addEventListener('click', function(e){ eventDelegation(e.target); }, false); function eventDelegation(target) { if (target && target.nodeName == 'LI') { switch (target.id) { case 'one': do something; return; case 'two': do something; return; case 'three': do something; return; } } return eventDelegation(target.parentNode); }
使用事件委托的優點
a.減少DOM操作,使事件處理時間減少。
b.減少記憶體空間的使用,提升性能。
因為在JavaScript中,每個函數都是對象,對象越多,占用的記憶體也就越多,合理使用事件委托可以減少記憶體的占用。
註意事項
比較適合使用事件委托的事件:
click
、mousedown
、mouseup
等,而如mouseout
、mouseover
等則不太適合使用事件委托(雖然mouseout
這些事件也冒泡,但通常需要確定元素的位置,所以不太推薦使用事件委托)。另外不會冒泡的事件是不適合使用事件委托的。