給列表元素添加點擊事件


如下html代碼,如何給一個列表中所有子元素添加點擊事件,輸出對應內容?

<ul id="container">
	<li id="li1">1</li>
	<li id="li2">2</li>
	<li id="li3">3</li>
	<li id="li4">4</li>
	<li id="li5">5</li>
</ul>

首先,循環列表,依次添加點擊事件:

for(var i = 1; i < 5; i++){
	document.getElementById('li' + i).addEventListener('click', function() {
		alert(i);
	})
}

似乎很容易理解這段代碼,但是實際上,不管點擊哪個<li>標簽,都會彈出數字5。還不清楚原因的同學,可以先來了解一下html事件處理程序和js作用域的相關知識。

有個很直接的方法,每次輸出li標簽對應的innerText即可。如果我一定要輸出這個i呢?可以使用閉包的方式:

for(var i = 1; i < 5; i++){
	(function(x){
		document.getElementById('li' + x).addEventListener('click', function(){
			alert(x)
		})
	})(i)
}

這里形如(function(){})()的代碼塊,叫做“立即被調用的函數表達式”(Immediately Invoked Function Expression)。可以思考,這里閉包如何產生?

另外,采用ES6新增的變量類型let,也可以快速的解決該問題。

for(let i = 1; i < 5; i++){
	document.getElementById('li' + i).addEventListener('click', function() {
		alert(i);
	})
}

用let代替var來聲明變量,就可以把變量的作用域限制在當前代碼塊中。變量i只存在於for循環中,一旦循環結束,在其他位置均無法訪問該變量。

上面方法都是通過循環,通過addEventListener方法分別給每個<li>標簽添加點擊事件。這樣做完全OK,不會導致什么問題。

但是在javaScript中,添加到頁面上的事件處理程序的數量,將直接關系到頁面的整體運行性能。首先,每個函數都是對象,都會占用內存;內存中的對象越多,性能就越差。其次,必須事先制定所有事件處理程序而導致的DOM訪問次數,會延遲整個頁面的交互就緒時間。

想象以上示例中,<li>標簽的數量很大時,循環為每個子元素添加事件,絕非好方法。下面給出一種優雅的方法,采用事件委托

document.getElementById('container').addEventListener('click', function(event) {
	var target = event.target;
	if(target.tagName == 'LI'){
		alert(target.innerText);
	}
}, false);

這段代碼里,使用事件委托只為<ul>元素添加一個onclick事件處理程序。因為有事件冒泡機制,單擊每個<li>標簽時,都會被這個函數處理。關於事件流,主要為事件捕獲階段與事件冒泡階段,可以另行了解。

參閱學習文檔:

You Don't Know JS — 第三章:作用域與閉包

ECMAScript 6 入門 — let 和 const 命令


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM