「從父元素來監聽子元素內容」是一種更好的事件監聽方式
我現在要做的功能是:
- 點擊
<li></li>後,會顯示「<li></li>裡面的文字內容」 - 如果是點擊「
<li></li>以外的東西」,就不會顯示任何內容
我的 jsbin 範例
https://jsbin.com/jivelig/edit?html,output
html:
1 | <ul class="list"> |
css:
1 | .list{ |
❌ JS 錯誤寫法
🎃 建立變數list,用.querySelector來選取「.list li」
🎃 在.list li做事件監聽–> 點擊.list li,就會執行「checkName 這個 function」
🎃 「checkName 這個 function」會印出「文字內容 e.target.textContent」
JS:
1 | // 點擊<li></li>後,會顯示「<li></li>裡面的文字內容」 |
用開發者工具來看:
- 點擊「第一個
<li></li>」(查理),的確會在 Console 出現「查理」
😢 但是,點擊「第二個<li></li>」(卡斯伯),在 Console 就不會出現「卡斯伯」

原因為:
用console.log(list);來看「變數list」選取到的東西,會發現–>
‼️ document.querySelector('.list li'); 只有選取到「第一個<li></li>」而已
🎃 .querySelector的特性:只會選取到「第一筆資料」

在「<ul></ul>」裡面,有很多個<li></li>,如果我希望,可以選取到「每一個<li></li>」來做事件監聽,我該怎麼做呢?
作法如下:
監聽父元素
💡 監聽父元素<ul></ul>–> 透過e.target,就可以去找出「父元素裡面的各種資訊」
💡 e.target - 了解目前點擊的是哪個元素
🎃 建立變數list,用.querySelector來選取「.list」
🎃 在「父元素.list」做事件監聽–> 點擊.list,就會執行「checkName 這個 function」
🎃 「checkName 這個 function」會印出「e.target」
1 | // 點擊<li></li>後,會顯示「<li></li>裡面的文字內容」 |
用開發者工具來看
🍋 我點擊「周圍區域」,e.target就是「<ul class="list">...</ul>」

🍋 我點擊「第一個<li></li>」,e.target就是「<li>查理</li>」

🍋 我點擊「第二個<li></li>」,e.target就是「<li>卡斯伯</li>」

🍋 就算我是「動態新增 html」,e.target也可以選取到「我點擊的元素」:
-
在「
<li>卡斯伯</li>」按右鍵,選擇「Edit as HTML」

-
新增一個「
<li>卡斯伯2</li>」

-
我點擊「第三個
<li></li>」,e.target就是「<li>卡斯伯2</li>」

但是,在「父元素<ul></ul>」裡面,有很多個子元素,我不希望點擊到「父元素 or 其他的子元素」,我只想要點擊到「<li></li>」
🍋 因為,我要做的功能是:點擊<li></li>後,會顯示「<li></li>裡面的文字內容」
我該怎麼做呢?
1️⃣ 用e.target.nodeName來確認「我點擊的東西是哪個節點」
🎃 用e.target.nodeName來確認「我點擊的東西是哪個節點」
🍋 先確認:我點擊的東西是不是「<li></li>」
1 | // 點擊<li></li>後,會顯示「<li></li>裡面的文字內容」 |
用開發者工具看:
🍋 我點擊「查理」,Console 就會出現「LI」,代表我點擊的是<li></li>

2️⃣ 秀出<li></li>的文字內容
❌ JS 錯誤寫法
💡 e.target.textContent代表「點擊目標的文字內容」
🎃 我在function checkName(e){}裡面寫「console.log(e.target.textContent);」
1 | // 點擊<li></li>後,會顯示「<li></li>裡面的文字內容」 |
用開發者工具看
- 如果我點擊的是「
<li></li>」,的確會出現「<li></li>的文字內容」

😢 但是,如果我點擊的是「<ul></ul>」,就會出現這種奇怪的狀態:

✅ 我希望「只有點擊<li></li>」時,才會出現「<li></li>的文字內容」。在點擊其他元素時,都不會出現任何內容。
該怎麼做呢?
3️⃣ 用e.target.nodeName去篩選元素
🎃 用if做判斷–> 當e.target.nodeName「不等於'LI'」時,就用return「回傳一個空值」
🍋 在return後面「不寫任何東西」,就代表「回傳一個空值」
🍋 只要執行了return,後面的程式碼console.log(e.target.textContent);就不會執行了
JS:
1 | // 點擊<li></li>後,會顯示「<li></li>裡面的文字內容」 |
用開發者工具看:
🍋 點擊「<li></li>以外的東西」–> 不等於li–> 執行return–> 後面的程式碼console.log(e.target.textContent);不會再繼續執行
–> Console 不會出現任何內容

return搭配 function 的特性
🎃 return除了可以「回傳值」之外,return也可以做為「function 的中斷點」
🍋 在 function 裡面:一旦執行了return,在return後面的程式碼就不會繼續執行了
1 | function checkName(e){ |
JS 這樣寫的好處
✅ 因為我監聽的是「父元素<ul></ul>」,我可以用「if判斷式」,去篩選出「父元素中,我想要選取的元素」
❌ 傳統的做法是「每個元素都綁定“監聽事件.addEventListener”」–> 效能會比較低落,因此不建議這麼做
1 | // 點擊<li></li>後,會顯示「<li></li>裡面的文字內容」 |