摘要:網上有關于事件委托的一個取快遞例子,十分生動,這里我對它作一些修改和拓展,然后通過程序來說明事件委托的機制。還有一個優點當增加新的節點時,自動攜帶父元素的事件效果。以上便是事件委托的基本思想。與其對應的還有事件捕獲。
事件委托(又名事件代理),就是利用事件冒泡,只指定一個事件處理程序,就可以管理某一類型的所有事件。
網上有關于事件委托的一個“取快遞”例子,十分生動,這里我對它作一些修改和拓展,然后通過程序來說明事件委托的機制。
某公司有三位員工,他們的快遞收件地址為公司,每當有快遞送達時,快遞員撥打其電話進行通知,他們接到電話后去取件。
員工ID | 員工名稱 | 聯系方式 |
---|---|---|
A | 甲 | 111111 |
B | 乙 | 222222 |
C | 丙 | 333333 |
對應到頁面,就是每個員工是一個標記:
每位員工接電話取快遞的行為就是一個個事件,這里我們假設收取快遞行為對應著onclick事件:
A.onclik = function() { 收取快遞; }; B.onclick = function() { 收取快遞; }; C.onclick = function() { 收取快遞; };
以上的實現,通常為通過循環遍歷每一個員工,為其增加事件:
/*程序1*/ var aUl = document.getElemengtByID("前臺工作人員"); var aLi = aUl.getElemengtsByTagName("li"); for (var i = 0; i < aLi.length; i++) { aLi[i].onclick = function() { 收取快遞; } }
可以看到,為每個員工都設置一個事件,會產生冗余代碼,占用內存,同時會進行多次DOM操作(與DOM節點進行交互),影響頁面運行性能。
“減少DOM操作是性能優化的主要思想之一”
于是,我們理所當然地想到:為什么不能讓前臺工作人員幫我們簽收快遞呢?
假設此時快遞員打電話通知員工甲取件(onclick),但員工甲的DOM節點
可以看到,這樣一來,不僅縮減代碼量,同時與DOM節點的交互次數也得到了縮減。
還有一個優點:當增加新的DOM節點時,自動攜帶父元素的事件效果。也就是說,當有一個新員工丁來公司后,前臺工作人員會直接幫他收取快遞,而無需專門為他設置事件。
例如,當新員工丁來到公司后:
... ... ... /*程序3*/ var aBtn = document.getElementById("btn"); aBtn.onclick = function() { var aLi = document.createElement("li"); oLi.innerHTML = "員工丁"; aUl.appendChild(aLi); } ...
在不使用事件委托的程序中,新增的員工丁是沒有事件的,我們需要用一個函數包含住程序1:
/*程序4*/ function pro1() { var aUl = document.getElemengtByID("前臺工作人員"); var aLi = aUl.getElemengtsByTagName("li"); for (var i = 0; i < aLi.length; i++) { aLi[i].onclick = function() { 收取快遞; } } }
然后在新增新員工丁的程序的末尾執行這個函數:
/*程序5*/ var aBtn = document.getElementById("btn"); aBtn.onclick = function() { ... pro1(); }
這樣做的缺點是顯而易見的:DOM節點交互次數成倍增加。
若我們采用事件委托機制來實現,就不會存在這個問題,子元素節點的onclick事件會直接在父元素節點得到執行。
到這里,我們會想到:對于同一種事件來說,使用事件委托將其放置在父元素節點上固然很方便。但如果對于不同的子元素節點要執行不同的事件呢,還能使用事件委托嗎?
答案是肯定的。
例如上述三位公司員工,總是使用固定品牌的快遞:
員工甲因為便宜,喜歡使用申通快遞,申通只送到園區大門;
員工乙是京東會員,總是購買京東自營商品,京東快遞送到樓下;
員工丙是順豐VIP,順豐快遞會送到送到所在樓層大廳。
他們三位在接到電話后,前臺工作人員需要去不同的地方取件,對于不使用事件委托的程序,需要對每個人設置獨特的處理事件:
var A = document.getElementById("A"); var B = document.getElementById("B"); var C = document.getElementById("C"); A.onclick = function() { 去園區大門取快遞; } B.onclick = function() { 去樓下取快遞; } C.onclick = function() { 去本層大廳取快遞; }
至少需要三次DOM操作,而且為每一個對應節點都設置了事件函數。
而若采用事件委托:
var aUl = document.getElementByID("前臺工作人員"); aUl.onclick = function (ev) { var target = ev.target || ev.srcElement; /*兼容瀏覽器*/ if (target.nodeName.toLocaleLowerCase() == "li") { switch(target.id) { case "A" : 去園區大門取快遞; break; case "B" : 去樓下取快遞; break; case "C" : 去本層大廳取快遞; break; } } }
這樣一來,DOM操作就只有一次,其他的操作都在JS內進行,可以有效提升網頁性能。
以上便是JS事件委托的基本思想。簡而言之,就是利用事件冒泡這一特點,來對事件進行管理,減少冗余代碼,減少不必要的創建,減少交互操作以節約內存和提高性能。
事件冒泡是當觸發某個DOM元素節點時,若該節點沒有對應事件,則檢查其父元素是否有對應事件,若有,則執行,若沒有,繼續向上檢查。與其對應的還有事件捕獲。
關于事件流的具體分析,將在以后的文章中總結。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/102543.html
摘要:見下圖更直觀在事件流中,事件的目標在捕獲階段不會接受到事件,這意味著在捕獲階段,事件從到后就停止了。下一個階段是目標階段,于是事件在上發生,并在事件處理中被看成是冒泡階段的一部分,然后,冒泡階段發生,事件又傳回。 CONTENTS DOM事件流 事件冒泡 阻止冒泡 事件捕獲 事件委托 DOM事件流 1.什么是事件流? 事件流所描述的是從頁面中接受事件的順序 2.DOM事件流的三個階...
摘要:見下圖更直觀在事件流中,事件的目標在捕獲階段不會接受到事件,這意味著在捕獲階段,事件從到后就停止了。下一個階段是目標階段,于是事件在上發生,并在事件處理中被看成是冒泡階段的一部分,然后,冒泡階段發生,事件又傳回。 CONTENTS DOM事件流 事件冒泡 阻止冒泡 事件捕獲 事件委托 DOM事件流 1.什么是事件流? 事件流所描述的是從頁面中接受事件的順序 2.DOM事件流的三個階...
摘要:見下圖更直觀在事件流中,事件的目標在捕獲階段不會接受到事件,這意味著在捕獲階段,事件從到后就停止了。下一個階段是目標階段,于是事件在上發生,并在事件處理中被看成是冒泡階段的一部分,然后,冒泡階段發生,事件又傳回。 CONTENTS DOM事件流 事件冒泡 阻止冒泡 事件捕獲 事件委托 DOM事件流 1.什么是事件流? 事件流所描述的是從頁面中接受事件的順序 2.DOM事件流的三個階...
摘要:案例說明使用原生完成桌面操作級應用,對于原生的掌握情況而言,是一個較為全面的綜合型案例。本次課從事件相關的功能入手,給大家帶來詳細的分享。 showImg(https://segmentfault.com/img/bVbh1qw); 案例說明:使用原生 JS 完成桌面操作級應用,對于原生 JS 的掌握情況而言,是一個較為全面的綜合型案例。本次課從事件(event)相關的功能入手,給大家...
摘要:本文是重溫基礎系列文章的第二十篇。事件捕獲為截獲事件提供機會,然后實際的目標接收到事件,最后事件冒泡,對事件作出響應。事件處理事件處理,即響應某個事件。包括導致事件的元素事件類型等其他信息。 本文是 重溫基礎 系列文章的第二十篇。 這是第三個基礎系列的第一篇,歡迎持續關注呀! 重溫基礎 系列的【初級】和【中級】的文章,已經統一整理到我的【Cute-JavaScript】的Java...
閱讀 1342·2021-09-24 10:26
閱讀 3655·2021-09-06 15:02
閱讀 605·2019-08-30 14:18
閱讀 577·2019-08-30 12:44
閱讀 3119·2019-08-30 10:48
閱讀 1936·2019-08-29 13:09
閱讀 1993·2019-08-29 11:30
閱讀 2279·2019-08-26 13:36