「從父元素來監聽子元素內容」是一種更好的事件監聽方式
我現在要做的功能是:
- 點擊
<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>裡面的文字內容」 |