摘要:事件代理原理事件代理本質(zhì)上來說是利用事件冒泡的機制來進行實現(xiàn)的。
概述
一般來說,我們在為前端頁面設(shè)計交互的的時候往往需要為DOM元素添加事件處理程序。但是很多時候頁面的DOM元素的結(jié)構(gòu)和層級會很復(fù)雜,如果我們?yōu)樗行枰砑邮录幚淼腄OM元素一一綁定上事件處理程序,那么不僅編寫出的代碼會很繁雜,整個頁面的性能也會很低下。比如我們有一個有序或者無序的列表,其中包裹了數(shù)百個子節(jié)點li,一般來說,在通過選擇器拿到元素集合后,我們會用for循環(huán)對集合進行遍歷,然后為其添加事件處理方法,這么做會帶來什么結(jié)果呢,在JS引擎中,代碼操作的DOM數(shù)量和添加的事件處理程序數(shù)量直接關(guān)系到頁面的整體性能。操作的DOM數(shù)量越多,對DOM的訪問次數(shù)越多,瀏覽器的重繪次數(shù)就越來越多,頁面的響應(yīng)速度和運行性能也就越來越差。所以,在進行程序優(yōu)化的過程,其中一個重要的思路就是減少DOM的操作。
這時,事件代理存在的重要意義就體現(xiàn)出來了,它為我們提供了一種新的解決為大量類似的DOM元素添加事件處理的解決方案。只為一個容器或者說父節(jié)點添加一次事件處理程序,就達成了控制這個容器中一系列元素的目標,大大的減少了瀏覽器對DOM的訪問。
事件代理原理事件代理本質(zhì)上來說是利用事件冒泡的機制來進行實現(xiàn)的。何為事件冒泡呢,百科中的解釋是當事件發(fā)生后,這個事件就要開始傳播(從里到外或者從外向里)。為什么要傳播呢?因為事件源本身(可能)并沒有處理事件的能力,即處理事件的函數(shù)(方法)并未綁定在該事件源上。例如我們點擊一個按鈕時,就會產(chǎn)生一個click事件,但這個按鈕本身可能不能處理這個事件,事件必須從這個按鈕傳播出去,從而到達能夠處理這個事件的代碼中(例如我們給按鈕的onclick屬性賦一個函數(shù)的名字,就是讓這個函數(shù)去處理該按鈕的click事件),或者按鈕的父級綁定有事件函數(shù),當該點擊事件發(fā)生在按鈕上,按鈕本身并無處理事件函數(shù),則傳播到父級去處理。
相關(guān)實現(xiàn)具體怎么實現(xiàn)事件代理呢,我們來看一些簡單的相關(guān)例子:
先寫一個簡單的有序列表結(jié)構(gòu)。
- 1
- 2
- 3
- 4
- 5
比如我們想要實現(xiàn)的是點擊li,彈出li的序列。如果要直接操作li。
var lists = document.querySelectorAll("li"); for(let i = 0; i < lists.length; i ++){ lists[i].onclick =function () { alert(lists[i].innerText); } }
通過選擇器拿到了li的集合,然后進行遍歷并一一綁定點擊事件,如果使用事件代理來實現(xiàn)呢
var lists = document.querySelector("ol"); lists.onclick = function (event) { alert(event.target.innerText); }
通過選擇器拿到li的容器也就是父節(jié)點ol,然后只綁定一次點擊事件,并通過event對象提供的屬性target指向容器的子節(jié)點,然后彈出該子節(jié)點的文本內(nèi)容。需要了解的是,event對象提供了兩個屬性,分別是currentTarget和target,前者指向的是綁定事件的當前節(jié)點,后者則指向當前節(jié)點的一級子節(jié)點。當我們面臨事件冒泡和事件捕獲時,這兩個屬性能夠為我們提供更高的靈活度。
上訴例子中,我們需要添加事件的DOM元素都是相同的,事件的種類也是一樣的,如果我們面對的是結(jié)構(gòu)更復(fù)雜一些的DOM集合呢,來看下面的例子。
DOM結(jié)構(gòu):
在這樣的DOM結(jié)構(gòu)中,我們要為四種不同的元素添加事件控制,如果只是通過target指向的話是無法實現(xiàn)的,需要挖掘target更深層的屬性來進行條件判斷,而target具備的屬性就是指向的子節(jié)點所具備的屬性,比如nodeName、id、className、value等
let box = document.querySelector(".wrap"); box.onclick = function (event) { if(event.target.nodeName === "button"){ //... }else if(event.target.value === "提交"){ //... }else if(event.target.className === "text"){ //... }else{ //... } };
這樣我們同樣只在父節(jié)點上綁定一次事件就完成了我們想要的效果,無論是編碼效率和性能損耗都比不適用事件代理的情況下更加優(yōu)化。我們可以發(fā)現(xiàn),相比與遍歷元素集合的方式,事件代理最大的好處就是減少了DOM的操作,從來提升了效能。
適用場景事件代理并非在所有場景中都適用的,在使用事件代理時,我們需要考慮添加事件處理的父節(jié)點能否觸發(fā)我們想要綁定的事件,比如:
當我們想為容器中的文本框綁定blur事件改變框體顏色時
let box = document.querySelector(".wrap"); box.addEventListener("blur",function (event) { event.target.style.borderColor = "red"; });
我們發(fā)現(xiàn)這樣做是無法生效的,應(yīng)為div元素是無法觸發(fā)onblur事件的,同時還有其他有關(guān)的輸入框事件也是無法觸發(fā)的,如oninput、onfocus等。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/100406.html
摘要:值得注意不同的瀏覽器使用不同的。今天截至年月,在瀏覽器進程中運行。這意味著瀏覽器進程包含一個實例,這是一個潛在的安全漏洞。 本文由云+社區(qū)發(fā)表作者:廖彩明 在從事前端開發(fā)過程中,瀏覽器作為最重要的開發(fā)環(huán)境,瀏覽器基礎(chǔ)是是前端開發(fā)人員必須掌握的基礎(chǔ)知識點,它貫穿著前端的整個網(wǎng)絡(luò)體系。對瀏覽器原理的了解,決定著編寫前端代碼性能的上限。瀏覽器作為JS的運行環(huán)境,學(xué)習(xí)總結(jié)下現(xiàn)代瀏覽器的相關(guān)知識...
摘要:禁止內(nèi)聯(lián)腳本執(zhí)行規(guī)則較嚴格,目前發(fā)現(xiàn)使用。合理使用上報可以及時發(fā)現(xiàn),利于盡快修復(fù)問題。因為事件會從目標元素一層層冒泡至對象。允許給一個事件注冊多個監(jiān)聽。表示在捕獲階段觸發(fā),表示在冒泡階段觸發(fā)。 關(guān)于【Step-By-Step】 Step-By-Step (點擊進入項目) 是我于 2019-05-20 開始的一個項目,每個工作日發(fā)布一道面試題。每個周末我會仔細閱讀大家的答案,整理最一份...
摘要:在標簽中添加屬性,本質(zhì)上是跟在標簽里面寫屬性時一樣的,所以屬性值最終都會編譯為字符串類型。這個節(jié)點包括很多,比如,以及一些方法等方法。一個對象有很多,該集合名字為,里面有其他以及,里面有很多。 一、變量類型和計算 JS中使用typeof能得到哪些類型 變量類型 值類型:變量本身就是含有賦予給它的數(shù)值的,它的變量本身及保存的數(shù)據(jù)都存儲在棧的內(nèi)存塊當中 引用類型:引用類型當然是分配到...
摘要:線程在執(zhí)行過程中與進程還是有區(qū)別的。但是線程不能夠獨立執(zhí)行,必須依存在應(yīng)用程序中,由應(yīng)用程序提供多個線程執(zhí)行控制。從邏輯角度來看,多線程的意義在于一個應(yīng)用程序中,有多個執(zhí)行部分可以同時執(zhí)行。 關(guān)于js 1.原型鏈 2.AJAX請求數(shù)據(jù)時解決緩存的辦法3.js的繼承 ...
閱讀 1265·2021-09-27 13:35
閱讀 2563·2021-09-06 15:12
閱讀 3380·2019-08-30 15:55
閱讀 2829·2019-08-30 15:43
閱讀 432·2019-08-29 16:42
閱讀 3446·2019-08-29 15:39
閱讀 3062·2019-08-29 12:28
閱讀 1239·2019-08-29 11:11