JavaScript中的事件處理機制分為兩個階段:捕獲和冒泡。當用戶觸發一個事件,它會沿著DOM樹的傳遞路徑向下傳遞,直到達到最終目標,然后再反向傳播回來。捕獲階段發生在冒泡階段之前,所以先觸發捕獲事件,再觸發冒泡事件。下面來詳細介紹一下JavaScript冒泡和捕獲。
下面我們以一個點擊事件的例子來介紹。
let grandfather = document.getElementById("grandfather");
let father = document.getElementById("father");
let son = document.getElementById("son");
// 冒泡
function bubbleHandler() {
console.log("bubble: " + this.id);
}
// 捕獲
function captureHandler() {
console.log("capture: " + this.id);
}
grandfather.addEventListener("click", bubbleHandler);
father.addEventListener("click", bubbleHandler);
son.addEventListener("click", bubbleHandler);
grandfather.addEventListener("click", captureHandler, true);
father.addEventListener("click", captureHandler, true);
son.addEventListener("click", captureHandler, true);
如上所述,我們在HTML中嵌套了三個div。然后使用addEventListener函數來添加了三個點擊事件處理程序,并在這三個事件處理程序中添加了兩個事件。第一次是冒泡事件,第二次是捕獲事件。addEventListener函數里的第三個參數(默認為false)表示點擊事件用的是冒泡還是捕獲。如果為true,表示用捕獲,否則表示用冒泡。
現在我們分別點擊grandfather,father和son這幾個元素,看看它們觸發的順序。我們可以看到在父元素中添加了冒泡事件處理程序后,當我們點擊子元素時會觸發該事件處理程序,然后將該事件逐級傳遞到祖先元素上。當祖先元素捕獲該事件時,它就會調用捕獲事件處理程序。下面是控制臺輸出結果:
// 從son元素開始,冒泡到grandfather:
bubble: son
bubble: father
bubble: grandfather
// 從grandfather元素開始,捕獲到son:
capture: grandfather
capture: father
capture: son
我們可以看到,在冒泡階段,點擊son時,先打印"bubble: son",隨后是"bubble: father",最后是"bubble: grandfather",即事件自下而上冒泡到最外層元素。而在捕獲階段,先打印"capture: grandfather",隨后是"capture: father",最后是"capture: son",即事件從最外層元素開始,自上而下捕獲到最內層元素。
總之,JavaScript提供了兩種事件處理機制,分別是捕獲和冒泡。當事件發生時,我們可以選擇將事件先在最外層元素上捕獲,再逐級向下傳遞,直到傳遞到目標元素?;蛘哌x擇先在目標元素上觸發事件,然后由目標元素向上傳遞到最外層元素。在實際開發中,我們應該根據具體的業務需求來選擇相應的事件機制。