W3C 規範中定義了3個事件階段,依次是捕獲階段 、 目標階段 、 冒泡階段。先捕獲,後冒泡,捕獲從上到下,就像石沉大海;而冒泡從下到上就像氣泡冒出水面。
先看個示例:
html 頁面:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>冒泡與捕獲</title>
</head>
<body style="border: blueviolet 3px solid">
<table style="border: saddlebrown 3px solid">
<tbody>
<tr>
<td>美杉</td>
<td>祿銘</td>
</tr>
<tr id="secondTr">
<td id="firstTd" style="border: olivedrab 3px solid">彥芸</td>
<td>陽騫</td>
</tr>
</tbody>
</table>
<script type="text/javascript" src="captureAndBubble2.js"></script>
</body>
</html>
js :
/*
* 冒泡與捕獲
* @author Deniro Lee
*/
let html = document.documentElement;
let body = document.body;
let table = body.querySelector('table');
let tbody = body.querySelector('tbody');
let secondTr = body.querySelector('#secondTr');
let firstTd = body.querySelector('#firstTd');
/**
* 冒泡回調
* @param event
*/
function bubbleCallback(event) {
let target = event.currentTarget;
console.log('bubble -> ' + target.tagName);
}
/**
* 捕獲回調
* @param event
*/
function captureCallback(event) {
let target = event.currentTarget;
console.log('capture -> ' + target.tagName);
}
html.addEventListener('click', captureCallback, true);
body.addEventListener('click', captureCallback, true);
table.addEventListener('click', captureCallback, true);
tbody.addEventListener('click', captureCallback, true);
secondTr.addEventListener('click', captureCallback, true);
firstTd.addEventListener('click', captureCallback, true);
html.addEventListener('click', bubbleCallback, false);
body.addEventListener('click', bubbleCallback, false);
table.addEventListener('click', bubbleCallback, false);
tbody.addEventListener('click', bubbleCallback, false);
secondTr.addEventListener('click', bubbleCallback, false);
firstTd.addEventListener('click', bubbleCallback, false);
在瀏覽器中運行以上頁面,點擊“彥芸”後,在 Console 中會看到冒泡與捕獲的過程運行結果:
點擊事件對象會按照圖 1 的傳播路徑依次完成捕獲、目標與冒泡階段。如果某個階段不支持或事件對象的傳播被終止,那麼該階段就會被跳過。
代碼中使用了addEventListener() 方法來跟蹤捕獲與冒泡階段事件。該方法的語法爲:
element.addEventListener(event, function, useCapture)
參數 | 描述 |
---|---|
event | 必須。字符串,指定事件名。注意: 不要使用 “on” 前綴。 例如,使用 “click” ,而不是使用 “onclick”。 |
function | 必須。指定要事件觸發時執行的函數。 當事件對象會作爲第一個參數傳入函數。 事件對象的類型取決於特定的事件。例如, “click” 事件屬於 MouseEvent(鼠標事件) 對象。 |
useCapture | 可選。布爾值,指定事件是否在捕獲或冒泡階段執行。可能值: true - 事件句柄會在捕獲階段執行; false- 默認值,事件句柄會在冒泡階段執行。 |
之前定義的腳本,我們使用 addEventListener() 方法先綁定捕獲方法,後綁定冒泡方法;如果我們交換下順序,先綁定冒泡然後再捕獲會怎樣?
html.addEventListener('click', bubbleCallback, false);
body.addEventListener('click', bubbleCallback, false);
table.addEventListener('click', bubbleCallback, false);
tbody.addEventListener('click', bubbleCallback, false);
secondTr.addEventListener('click', bubbleCallback, false);
firstTd.addEventListener('click', bubbleCallback, false);
html.addEventListener('click', captureCallback, true);
body.addEventListener('click', captureCallback, true);
table.addEventListener('click', captureCallback, true);
tbody.addEventListener('click', captureCallback, true);
secondTr.addEventListener('click', captureCallback, true);
firstTd.addEventListener('click', captureCallback, true);
運行結果:
可以發現目標元素的冒泡事件先於捕獲事件執行,其它元素順序不變。也就是說,綁定順序隻影響到目標元素的事件發生順序。