DOM事件的傳播機制是指當一個事件在DOM樹中觸發時,它是如何在各個元素之間傳播的。DOM事件傳播機制分為三個階段:捕獲階段、目標階段和冒泡階段。此外,還有一種常用的技術稱為事件委托,它能夠簡化事件處理程序的綁定和管理。本文將詳細介紹這些概念,并提供相應的代碼示例。
事件與事件流
在介紹事件傳播機制之前,我們先來了解一下什么是事件和事件流。在DOM中,事件是指用戶與頁面交互時發生的動作,比如點擊、鼠標移動等。而事件流則是指這些事件在DOM樹中傳播的路徑。
每次用戶與一個網頁進行交互,例如點擊鏈接,按下一個按鍵或者移動鼠標時,就會觸發一個事件。我們的程序可以檢測這些事件,然后對此作出響應。從而形成一種交互。
這樣可以使我們的頁面變得更加的有意思,而不僅僅像以前一樣只能進行瀏覽。
JavaScript 中采用一個叫做事件監聽器的東西來監聽事件是否發生。這個事件監聽器類似于一個通知,當事件發生時,事件監聽器會讓我們知道,然后程序就可以做出相應的響應。
通過這種方式,就可以避免讓程序不斷地去檢查事件是否發生,讓程序在等待事件發生的同時,可以繼續做其他的任務。
標準 DOM 事件流
DOM事件流是指在DOM樹中,事件從最外層的節點開始傳播,逐級向下,直到達到目標節點,然后再從目標節點向上傳播到最外層的節點。
DOM事件流分為三個階段:捕獲階段、目標階段和冒泡階段。
- 捕獲階段:事件從最外層的節點開始傳播,逐級向下,直到達到目標節點。在捕獲階段中,事件會依次觸發每個經過的節點上綁定的捕獲型事件處理函數。
- 目標階段:事件達到目標節點后,在目標節點上觸發綁定的事件處理函數。在這個階段中,只會觸發目標節點上綁定的事件處理函數。
- 冒泡階段:事件從目標節點開始向上傳播,逐級向上,直到達到最外層的節點。在冒泡階段中,事件會依次觸發每個經過的節點上綁定的冒泡型事件處理函數。
在實際應用中,默認情況下大部分DOM事件都是按照冒泡方式進行傳播。但是也可以通過調用addEventListener
方法時傳入第三個參數為true
來將其設置為捕獲方式進行傳播。
總結起來,DOM事件流就是指從最外層的節點開始傳播,逐級向下到達目標節點,然后再從目標節點向上傳播到最外層的節點的過程。這個過程分為捕獲階段、目標階段和冒泡階段。
下面是一個示例,演示了標準 DOM 事件流的傳播順序:
<div id="outer"><div id="inner"><button id="btn">點擊我</button></div>
</div>
const outer = document.getElementById('outer');
const inner = document.getElementById('inner');
const btn = document.getElementById('btn');outer.addEventListener('click', function() {console.log('外層元素被點擊');
}, true);inner.addEventListener('click', function() {console.log('內層元素被點擊');
}, true);btn.addEventListener('click', function() {console.log('按鈕被點擊');
});
當我們點擊按鈕時,控制臺會輸出以下內容:
外層元素被點擊 內層元素被點擊 按鈕被點擊
可以看到,事件首先在捕獲階段從外層元素開始傳播,然后到達目標元素,最后在冒泡階段從目標元素向上冒泡。
事件冒泡流
事件冒泡是指在DOM樹中,事件從目標元素開始向上冒泡傳播的過程。也就是說,在冒泡階段,事件會依次觸發父級元素的相同類型事件處理程序。
下面是一個示例,演示了事件冒泡的過程:
<div id="outer"><div id="inner"><button id="btn">點擊我</button></div>
</div>
const outer = document.getElementById('outer');
const inner = document.getElementById('inner');
const btn = document.getElementById('btn');outer.addEventListener('click', function() {console.log('外層元素被點擊');
});inner.addEventListener('click', function() {console.log('內層元素被點擊');
});btn.addEventListener('click', function() {console.log('按鈕被點擊');
});
當我們點擊按鈕時,控制臺會輸出以下內容:
按鈕被點擊 內層元素被點擊 外層元素被點擊
可以看到,事件首先在目標元素上觸發,然后在冒泡階段依次觸發父級元素的相同類型事件處理程序。
事件捕獲流
事件捕獲是指在DOM樹中,事件從最外層的父級元素開始向下捕獲傳播的過程。也就是說,在捕獲階段,事件會依次觸發父級元素的相同類型事件處理程序。
下面是一個示例,演示了事件捕獲的過程:
<div id="outer"><div id="inner"><button id="btn">點擊我</button></div>
</div>
const outer = document.getElementById('outer');
const inner = document.getElementById('inner');
const btn = document.getElementById('btn');outer.addEventListener('click', function() {console.log('外層元素被點擊');
}, true);inner.addEventListener('click', function() {console.log('內層元素被點擊');
}, true);btn.addEventListener('click', function() {console.log('按鈕被點擊');
});
當我們點擊按鈕時,控制臺會輸出以下內容:
外層元素被點擊 內層元素被點擊 按鈕被點擊
可以看到,事件首先在捕獲階段依次觸發父級元素的相同類型事件處理程序,然后到達目標元素。
事件委托流
事件委托是一種常用的技術,它利用了事件冒泡的特性。通過在父級元素上綁定一個事件處理程序,可以監聽子級元素觸發的事件。這樣一來,無論子級元素是已經存在的還是動態生成的,都可以通過父級元素來管理它們的事件。
下面是一個示例,演示了事件委托的過程:
<ul id="list"><li>列表項1</li><li>列表項2</li><li>列表項3</li>
</ul>
const list = document.getElementById('list');list.addEventListener('click', function(event) {if (event.target.tagName === 'LI') {console.log('列表項被點擊');console.log('觸發事件的目標元素是:', event.target);}
});
當我們點擊任意一個列表項時,控制臺會輸出以下內容:
列表項被點擊 觸發事件的目標元素是: <li>列表項1</li>
可以看到,通過在父級元素上綁定點擊事件處理程序,我們可以捕獲到子級元素觸發的點擊事件,并且可以獲取到觸發事件的目標元素。這樣一來,無論我們添加或刪除列表項,只需要在父級元素上綁定一個事件處理程序即可。
總結
通過以上介紹,我們了解了DOM事件傳播機制的三個階段:捕獲階段、目標階段和冒泡階段。此外,我們還學習了如何利用事件委托來簡化事件處理程序的綁定和管理。掌握這些概念和技巧,能夠幫助我們更好地處理和管理DOM中的各種交互事件。