Javascript 的事件傳播
事件傳播 = 事件流,就是描述頁面中接受事件的順序。大致上,可以分成兩種機制:
- 冒泡(Bubbling)。
- 捕獲(Capture)。
冒泡
代表從觸發事件的元素開始,向外傳遞,直到網頁的根節點為止。如下方程式碼所式,我們點擊了 <h1> 元素,事件將會層層向外傳遞。
其順序為:<h1> -> <body> -> <html> -> document -> window。
html
<!DOCTYPE html>
<html>
<head>
<title>Javascript - 事件傳遞</title>
</head>
<body>
<h1>click</h1>
</body>
</html>測試以下程式碼,從最內層向外傳遞。以 console.log() 印出來的內容,
依序為:in -> middle -> out -> body -> html -> document -> window。
html
<!DOCTYPE html>
<html>
<head>
<title>Javascript - 事件傳遞</title>
</head>
<body>
<div class="box-out" id="BoxOut">
<div class="box-middle" id="BoxMiddle">
<div class="box-in" id="BoxIn"></div>
</div>
</div>
</body>
</html>js
window.addEventListener('click', () => {
console.log('window');
}, false)
document.addEventListener('click', () => {
console.log('document');
}, false);
document.querySelector('html').addEventListener('click', () => {
console.log('html');
}, false);
document.body.addEventListener('click', () => {
console.log('body');
}, false);
document.querySelector('#BoxOut').addEventListener('click', () => {
console.log('out');
}, false);
document.querySelector('#BoxMiddle').addEventListener('click', () => {
console.log('middle');
}, false);
document.querySelector('#BoxIn').addEventListener('click', () => {
console.log('in');
}, false);css
body, html {
height: 100%;
}
.box-out {
width: 500px;
}
.box-out,
.box-middle,
.box-in {
padding: 30px;
}
.box-out {
background-color: yellowgreen;
}
.box-middle {
background-color: cadetblue;
}
.box-in {
background-color: pink;
}TIP
監聽器的第三個參數為選填,在沒有設定的狀況下,預設為 false。因此,若沒有設定或設定為 false 都是向外傳遞的冒泡機制,
捕獲
此傳遞的方式剛好與冒泡相反,也就是由外向內傳遞。以下方的程式碼為例:
其順序為:window -> document -> <html> -> <body> -> <h1>。
html
<!DOCTYPE html>
<html>
<head>
<title>Javascript - 事件傳遞</title>
</head>
<body>
<h1>click</h1>
</body>
</html>測試以下程式碼,從最外層向內傳遞。以 console.log() 印出來的內容,
依序為:window -> document -> html -> body -> out -> middle -> in。
html
<!DOCTYPE html>
<html>
<head>
<title>Javascript - 事件傳遞</title>
</head>
<body>
<div class="box-out" id="BoxOut">
<div class="box-middle" id="BoxMiddle">
<div class="box-in" id="BoxIn"></div>
</div>
</div>
</body>
</html>js
window.addEventListener('click', () => {
console.log('window');
}, true)
document.addEventListener('click', () => {
console.log('document');
}, true);
document.querySelector('html').addEventListener('click', () => {
console.log('html');
}, true);
document.body.addEventListener('click', () => {
console.log('body');
}, true);
document.querySelector('#BoxOut').addEventListener('click', () => {
console.log('out');
}, true);
document.querySelector('#BoxMiddle').addEventListener('click', () => {
console.log('middle');
}, true);
document.querySelector('#BoxIn').addEventListener('click', () => {
console.log('in');
}, true);css
body, html {
height: 100%;
}
.box-out {
width: 500px;
}
.box-out,
.box-middle,
.box-in {
padding: 30px;
}
.box-out {
background-color: yellowgreen;
}
.box-middle {
background-color: cadetblue;
}
.box-in {
background-color: pink;
}阻擋事件傳播 event.stopPropagation()
如果要阻擋事件外擴張,就可以利用到事件物件中的方法: event.stopPropagation()。
html
<!DOCTYPE html>
<html>
<head>
<title>Javascript - 事件傳遞</title>
</head>
<body>
<div class="box-out" id="BoxOut">
<div class="box-in" id="BoxIn"></div>
</div>
</body>
</html>js
document.querySelector('#BoxOut').addEventListener('click', () => {
console.log('out');
});
document.querySelector('#BoxIn').addEventListener('click', (e) => {
e.stopPropagation();
console.log('in');
});css
.box-out,
.box-in {
padding: 30px;
}
.box-out {
background-color: yellowgreen;
}
.box-in {
background-color: pink;
}取消預設行為 event.preventDefault()
在 HTML 的元素中,有某些元素都有預設行為。像是 <a> 會有連結的動作、<input type="submit"> 會有送出表單的動作。如果我們需要綁定某些事件在元素上,但元素上卻有一些預設的 HTML 行為,將會影響我們安排好的工作。這樣一來,取消預設行為就是一件很重要的事情。
html
<a id="Link" href="http://tw.yahoo.com">前往 Yahoo!</a>js
document.querySelector('#Link').addEventListener('click', (e) => {
e.preventDefault();
});