上一篇講到event傳遞時的三種phase,形成事件capturing和bubbling
再來整理相關的應用,加深印象
Event Delegation(事件代理)
由父元素取代子元素註冊事件
範例: (取自JavaScript Event Delegation)
<ul id="menu">
<li><a id="home">home</a></li>
<li><a id="dashboard">Dashboard</a></li>
<li><a id="report">report</a></li>
</ul>
當每個選單項目都想綁定click事件,可能會這樣寫
let home = document.querySelector('#home');
home.addEventListener('home',(event) => {
console.log('Home menu item was clicked');
});
let dashboard = document.querySelector('#dashboard');
dashboard.addEventListener('dashboard',(event) => {
console.log('Dashboard menu item was clicked');
});
let report = document.querySelector('#report');
report.addEventListener('report',(event) => {
console.log('Report menu item was clicked');
});
當項目越來越多 or 頁面越來越複雜,可能就會註冊很多個event handler,效能不好
利用event傳播的機制,可以改寫成:
let menu = document.querySelector('#menu');
menu.addEventListener('click', (event) => {
let target = event.target;
switch(target.id) {
case 'home':
console.log('Home menu item was clicked');
break;
case 'dashboard':
console.log('Dashboard menu item was clicked');
break;
case 'report':
console.log('Report menu item was clicked');
break;
}
});
當點擊ul中的a連結時,因為event bubbling
最後會傳遞給ul元素,所以由父元素代為綁定event
而透過target id 可以區分是哪個目標被點擊
小結event delegation的優點:
-
減少記憶體的消耗, 增加效能
-
減少在頁面中註冊多個event handler
Event Stop Propagation
這篇Event Capturing and Bubbling in JavaScript有提到,知道event的傳播機制,Who care?? (都用預設bubbling就好??)
看起來不重要,踩到雷就知道
除了event delegation,最常遇到的應該是彈跳視窗(for 手刻)
彈跳視窗出現後,通常有兩種方式可以關閉
- 點擊彈跳視窗的x
- 點擊彈跳視窗以外的區域
範例 (取自 JavaScript Capture Bubble DOM事件獲取&冒泡)
See the Pen popup sample by pengyushan (@pengpon77) on CodePen.
小結:
- 選定capturing or bubbling傳遞方式
- target到達後,不再往上或往下傳,使用
e.stopPropagation()
中斷 - 彈出視窗事件僅綁定在button上,click不再往下傳!!
- 關閉視窗事件除綁在x span上,也要綁定在整個document上
- 跳窗本身被點擊後,要阻止事件繼續傳給document!
或是利用event target來控制跳窗的開啟或關閉
See the Pen Simple Confirmation Popup by Adventures in Missions (@adventuresinmissions) on CodePen.