天天看點

JavaScript 性能優化技巧:事件委托

DOM 的各種事件為豐富的互動提供了可能,在現在的 web 應用程式中,事件處理程式越來越多,越來越複雜,頁面中随處可見的事件監聽已經司空見慣,但這引出了一個性能的問題,事件監聽得越多,頁面運作性能就越差。主要原因來自兩個方面:<b>1.</b> 每添加一個事件監聽,載入頁面時都會增加一次對被監聽節點的通路,這無疑增加了頁面完全準備就緒所需的時間;<b>2.</b> 每一個事件監聽函數都會占用記憶體,而 JavaScript 并不具備配置設定記憶體的權利,有限的記憶體如果被事件監聽函數占用得越多,頁面性能下降得也越多。

假如有下面的一個無序清單,需要在每一個 li 被點選之後添加或移除一個名為 'active' 的 class 用以标記該項為紅色或還原。

在上面的代碼中通過 jQuery 的選擇器,找到了這個無序清單中的每一個 li 元素,并為其綁定了 click 事件,代碼看上去很簡單,但實際上 $('#list li') 傳回了一個數組,在這個數組中包含了 5 個上面的 li 元素,然後通過疊代為這 5 個元素分别綁定了一個事件處理函數,這意味着當這段 JavaScript 代碼被執行過後,記憶體中多了 5 個對象。

事件委托的原理是事件冒泡,這個過程大緻如下圖所示:

JavaScript 性能優化技巧:事件委托

圖中右邊部分 (Bubbling Phase) 即為事件冒泡的過程,當元素的一個事件被觸發後,這個事件會像冒泡一樣一直向上(父元素)傳遞,直到 document ( Firefox ,Chrome ,Safari 冒泡到 window),事件委托的核心就是監聽一個 DOM 中更高層、更不具體的元素,等到事件冒泡到這個不具體元素時,通過 event 對象的 target 屬性來擷取觸發事件的具體元素。下面的代碼使用了事件委托的方法改進了這個事件處理函數。

在這裡,被監聽的元素變成了 ul,即剛才所說的不具體的元素。由于事件的冒泡,在每一個 li 上的 click,都會觸發 ul 的事件監聽,然後通過 event 中的 target 這個指向事件目标(具體元素)的屬性擷取到被點選到的那個 li ,最後切換 class 'active' 的有無,任務完成。

通過使用事件委托這個技巧,達到相同的目标隻監聽了一個元素的事件,同樣也隻添加了 1 個事件處理函數。浏覽器為添加事件所要查找并引用的 DOM 更少,由于監聽函數變少,記憶體的使用也同時減少了。如果頁面上需要添加事件的元素很多,事件委托對于頁面性能改善的作用是不可小視的。

繼續閱讀