理解js的事件冒泡和事件捕獲
定義
冒泡:作用於子元素上的事件會一級一級向上傳遞,類似於冒泡的形式。
捕獲:作用於父元素的事件會一級一級向下傳遞到最終的子元素。
使用方法
文件請參考addEventListener,以及runnoob的addEventListener
EventTarget.addEventListener()語法:
element.addEventListener(event, function, useCapture)
注意useCapture引數,他是一個boolean值,指定事件是否在捕獲或冒泡階段執行。預設為false,如果指定為true,表明在捕獲階段執行,指定為true,表明在冒泡階段執行。
案例參考
先看如下程式碼:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test</title>
<style>
#parent {
height: 300px;
background-color: #bcbcbc;
}
#son {
margin-top: 100px;
height: 100px;
background-color: green;
}
</style>
</head>
<body>
<div id="parent">
我是父親
<div id="son">我是兒子</div>
</div>
<script>
function handler(event) {
console.log('target: ', event.target);
console.log('curtrentTarget: ', event.currentTarget);
}
let pa = document.getElementById('parent');
pa.addEventListener('click', handler, false);
let son = document.getElementById('son');
son.addEventListener('click', handler, false);
</script>
</body>
</html>
使用瀏覽器執行這段程式碼,效果如下:
我們點選兒子div,控制檯列印如下:
可以看到第一次列印的target和currentTarget都是son,而第二次事件冒泡到了parent,此時target是son,currentTarget變成了parent。
事件捕獲
我們把程式碼中的useCapture改為true:
let pa = document.getElementById('parent');
pa.addEventListener('click', handler, true);
let son = document.getElementById('son');
son.addEventListener('click', handler, true);
然後再次執行,結果如圖:
此時事件實在捕獲階段執行,也就是說會先觸發parent的click事件。
target和currentTarget的區別
仔細看前面的列印資訊就知道了,target始終不變,它代表觸發事件的那個元素(不管是冒泡階段還是捕獲階段都是指最底層的元素(這裡指son)。而currentTarget則表示當前階段註冊了EventListener的元素。
如何阻止冒泡和捕獲階段事件的進一步傳播
文件參考:event.stopPropagation
API用法:
event.stopPropagation()
修改我們的程式碼,在handler中加入event.stopPropagation():
function handler(event) {
console.log('target: ', event.target);
console.log('curtrentTarget: ', event.currentTarget);
event.stopPropagation();
}
再次執行,點選兒子div,列印出來的日誌如下(冒泡階段):
捕獲階段列印日誌:
可以看到,冒泡階段,點選事件沒有繼續向上傳播到父元素;捕獲階段,點選事件沒有繼續向下傳播到子元素。
P.S. 請考慮下在handler方法中,this到底指向target還是currentTarget呢?