1. 程式人生 > >事件委託(記憶體和效能)

事件委託(記憶體和效能)

導語

在 JavaScript 中,新增到頁面上的事件處理程式數量將直接關係到頁面的整體執行效能。導致這一問題的原因是是多方面的:
1.每個函式都是物件,都會佔用記憶體;記憶體中的物件越多,效能就越差;
2.必須事先指定所有事件處理程式而導致的 DOM 訪問次數,會延遲整個頁面的互動就緒時間。

事件委託:對“事件處理程式過多”問題的解決方案。

事件委託利用了事件冒泡,只指定一個事件處理程式,就可以管理某一型別的所有事件。例如,click 事件會一直冒泡到 document 層次。也就是說,我們可以為整個頁面指定一個 onclick 事件處理程式,而不必給每個可單擊的元素分別新增事件處理程式。

HTML 程式碼:

<ul id="myLinks">
    <li id="goSomewhere">Go somewhere</li>
    <li id="doSomething">Do something</li>
    <li id="sayHi">Say hi</hi>
</ul>

上面例子包含3個被點選後會執行操作的列表項。按照傳統的做fa是為它們新增3個事件處理程式:

var item1 = document.getElementById("goSomewhere");
var item2 = document.getElementById("doSomething");
var item3 = document.getElementById("sayHi");

EventUtil.addHandler(item1,"click",function(event){
    location.href = "http://www.wrox.com";
});

EventUtil.addHandler(item2,"click",function(event){
    document.title = "I changed the document's title";
});

EventUtil.addHandler(item3,"click",function(event){
    alert("hi");
});

如果在一個複雜的 Web 應用程式中,對所有可點選的元素都採用這種方式,那麼結果就會有數不清的程式碼用於新增事件處理程式。此時,可以利用事件委託技術解決這個問題。使用事件委託,只需在 DOM 樹中儘量最高的層次上新增一個事件處理程式,如下面所示:

var list = document.getElementById("myLinks");

EventUtil.addHandler(list,"click",function(event){
    event = EventUtil.getEvent(event);
    var target = EventUtil.getTarget(event);
    switch(target.id){
        case "doSomething":
            document.title = "I changed the document's title";
            break;
        case "goSomewhere":
            location.href = "http://www.wrox.com";
            break;
        case "sayHi":
            alert("hi");
            break;
    }
});

在這段程式碼裡,我們使用事件委託只為<ul>元素添加了一個onclick事件處理程式。由於所有列表項都是這個子元素的子節點,而且它們的事件會冒泡,所以單擊事件最終會被這個函式處理。我們知道事件目標是被單擊的列表項,故而可以通過檢測 id 屬性來決定採取適當的操作。與前面未使用事件委託的程式碼比一比,會發現這段程式碼的事前消耗更低,因為只取得了一個 DOM 元素,只添加了一個事件處理程式。雖然對使用者來說最終的結果相同,但這種技術需要佔用的記憶體更少。

所有用到按鈕的事件(多數滑鼠事件和鍵盤事件)都適合採用時間委託技術。

如果可行的話,也可以考慮為 document 物件新增一個事件處理程式,用以處理頁面上發生的某種特定型別的事件。這樣做與傳統的做法相比具有如下優點:
1.document 物件很快就可以訪問,而且可以在頁面生命週期的任何時點上為它新增事件處理程式(無需等待 DOMContentLoaded 或 load 事件)。換句話說,只要可單擊的元素呈現在頁面上,就可以立即具備適當的功能。
2.在頁面中設定事件處理程式所需的時間更少。只新增一個事件處理程式所需的 DOM 引用更少,所花的時間也更少。
3.整個頁面佔用的記憶體空間更少,能夠提升整體效能。

最適合採用事件委託技術的事件包括 click、mousedown、mouseup、keyup 和 keypress。雖然 mouseover 和 mouseout 事件也冒泡,但要適當處理它們並不容易,而且經常需要計算元素的位置。(因為當滑鼠從一個元素移到其子節點時,或者當滑鼠移出該元素時,都會觸發 mouseout 事件)。