JavaScript 事件委託

在談到前端性能優化時,相信大家對其中一條優化策略有印象:“善於使用事件委託”。那麼什麼是事件委託?事件委託又是怎樣提高前端性能的呢?

出現背景

由於事件處理程序可以爲現代Web應用程序提供交互能力,因此許多開發人員不分青紅皁白地向頁面中添加大量的處理程序。在JavaScript中,添加到頁面上的事件處理程序數量將直接關係到頁面的整體運行性能。導致這一問題的原因是多方面的。首先,每個函數都是對象,都會佔用內存;內存中的對象越多,性能就越差。其次,必須事先指定所有事件處理程序而導致的DOM訪問次數,會延遲整個頁面的交互就緒時間。

事件委託

對“事件處理程序過多”問題的解決方案就是事件委託。事件委託利用了事件冒泡,核心原理是:給父節點添加偵聽器,利用事件冒泡影響每一個子節點。表現形式爲:只指定一個事件處理程序,就可以管理某一類型的所有事件。例如,click事件會一直冒泡到document層次。也就是說,我們可以爲整個頁面指定一個onclick事件處理程序,而不必給每個可單擊的元素分別添加事件處理程序。看下面的例子:

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

一個無序列表內部包含三個列表項,如果我們想爲這三個列表項添加事件處理程序,傳統的做法爲:

var item1 = document.getElementById("goSomewhere");
var item2 = document.getElementById("doSomething");
var item3 = document.getElementById("sayHi");
item1.addEventListener("click", function(e){
location.href = "https://www.baidu.com";
}, false);
item2.addEventListener("click", function(e){
document.title = "I changed the document's title";
}, false);
item3.addEventListener("click", function(e){
alert("hi");
}, false);

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

var list = document.getElementById("myLinks");
myLinks.addEventListener("click", function(e){
	switch(e.target.id){
		case "goSomewhere":
			location.href = "https://www.baidu.com";
			break;
		case "doSomething":
			document.title = "I changed the document's title";
			break;
		case "sayHi":
			alert("hi");
			break;
	}
}, false);

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章