在使用 JavaScript 事件委托時,開發者常會遇到一個經典問題:綁定在父元素(如 <ul>)上的事件處理函數,在處理子元素(如 <li>)觸發的事件時,event.target 指向的往往是子元素內部的元素(例如 <img>),而非預期的 <li> 本身。這導致無法通過 target.id 正確識別是哪個列表項被點擊。
以下是一個典型的圖片輪播切換場景:
<ul class="num">
<li id="li1"><img src="num.jpg"></li>
<li id="li2"><img src="num.jpg"></li>
<li id="li3"><img src="num.jpg"></li>
<li id="li4"><img src="num.jpg"></li>
</ul>
<script>
var ul = document.getElementsByTagName("ul")[0];
ul.onmouseover = function(event) {
event = event || window.event;
var target = event.target || event.srcElement;
// 問題在這裡:若滑鼠移入 li 內部的 img,target 會是 img,而 img 沒有 id
switch(target.id) {
case "li1": /* ... */ break;
case "li2": /* ... */ break;
// ...
}
};
</script>
事件冒泡機制使得父元素能捕獲子元素的事件,但 event.target 始終指向**實際觸發事件的最深層元素**。當 <li> 內部包含 <img> 時,滑鼠移入圖片區域會觸發 mouseover,此時 target 是 <img>,而非 <li>。
利用 event.currentTarget 或向上遍歷 DOM 尋找目標元素。最簡潔的寫法是:
var target = event.target || event.srcElement;
// 如果 target 沒有 id,則取其父節點的 id
var liId = target.id || target.parentNode.id;
switch(liId) {
case "li1": /* ... */ break;
case "li2": /* ... */ break;
// ...
}
event.currentTarget 可直接獲取綁定事件的元素(即 <ul>),但這裡需要的是具體的 <li>。.closest())。addEventListener 並配合 event.delegateTarget 或手動委托邏輯。事件委托的關鍵在於理解 target 與 currentTarget 的區別。通過 target.id || target.parentNode.id 這一簡單技巧,即可優雅解決內部元素干擾的問題,保持代碼簡潔高效。