首頁 >web前端 >js教程 >JavaScript事件委託的詳細介紹(附程式碼)

JavaScript事件委託的詳細介紹(附程式碼)

不言
不言轉載
2019-03-15 14:23:142104瀏覽

這篇文章帶給大家的內容是關於JavaScript事件委託的詳細介紹(附程式碼),有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

事件委託(又稱事件代理),就是利用事件冒泡,只指定一個事件處理程序,就可以管理某一類型的所有事件。

網路上有關於事件委託的一個「取快遞」例子,十分生動,這裡我對它作一些修改和拓展,然後透過程式來說明事件委託的機制。

某公司有三位員工,他們的快遞收件地址為公司,每當有快遞送達時,快遞員撥打其電話進行通知,他們接到電話後去取件。

員工ID 員工名稱 聯絡人
A 111111
#B B 222222
#C C 333333
#對應到頁面,就是每個員工是一個標記:
<ul id="前台工作人员">
    <li id="A">员工甲</li>
    <li id="B">员工乙</li>
    <li id="C">员工丙</li>
</ul>

每位員工接電話取快遞的行為就是一個個事件,這裡我們假設收取快遞行為對應著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操作是效能最佳化的主要想法之一」

於是,我們理所當然地想到:為什麼不能讓前台工作人員幫我們簽收快遞呢?

<ul id="前台工作人员">
    <li id="A">员工甲</li>
    <li id="B">员工乙</li>
    <li id="C">员工丙</li>
</ul>

/*程序2*/
var tel = document.getElementById("前台工作人员");
tel.onclick = function() {
    收取快递;
}

假設此時快遞員打電話通知員工甲取件(onclick),但員工甲的DOM節點

  • 並無對應事件(onclick),所以這個事件會「冒泡」到
  • 的父元素
      ,發現
        上有onclick處理事件,於是觸發該事件,由前台工作人員收取快遞。

        可以看到,這樣一來,不僅縮減程式碼量,同時與DOM節點的交互次數也得到了縮減。

        還有一個優點:當增加新的DOM節點時,自動攜帶父元素的事件效果。也就是說,當有新員工丁來公司後,前台工作人員會直接幫他收取快遞,而無需專門為他設定事件。

        例如,當新員工丁來到公司後:

        ...
        <input type="button" id="btn" value="添加新员工">
        ...
        
        ...
        /*程序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.getElemengtByID("前台工作人员");
        aUl.onclick = function (ev) {
            var target = ev || window.event; /*兼容浏览器*/
            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元素節點時,若該節點沒有對應事件,則檢查其父元素是否有對應事件,若有,則執行,若沒有,繼續向上檢查。與其對應的還有事件捕獲

        #

        以上是JavaScript事件委託的詳細介紹(附程式碼)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

  • 陳述:
    本文轉載於:segmentfault.com。如有侵權,請聯絡admin@php.cn刪除