![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiY4ETZhJzNx0TZjJXdvN3PnBnaucHM0QTMfNmMzImZ0ADNkRDOkJjM5E2YlBTZzUDMzEmNxEjY2UTOtIjdvwVbvNmLn1WaopnLxMWaw9CXvwlOzBHd0hWPsJXdmYDM3YjZkJGNzQDNl1SOhRGOtETMiVWLwMTZw0yMlBDZkJDZ50DZpV3ZmITPlBXe0ZyPldWYtl2LcdXZpZ3Lc12bj5SZjVjL5h3byBnLxATLn1Wavw1LcpDc0RHaiojIsJye.jpg)
- 通過設定
的第三個參數可以決定事件是否在捕獲階段觸發。addEventListener
- 通過
可以阻止事件冒泡。event.stopPropagation()
一、定義
DOM結構是一個樹型結構,當一個HTML元素觸發一個事件時,該事件會在元素結點與根結點之間的路徑傳播,路徑所經過的結點都會收到該事件,這個傳播過程可稱為 DOM 事件流(DOM event flow )。
點選檢視W3C對事件流的定義,裡面有事件在dom樹上傳播過程的圖檔。
傳播(Propagation)按順序分三個階段(Any event taking place in the W3C event model is first captured until it reaches the target element and then bubbles up again):
- 捕獲階段(capture phrase,從根節點window到目标節點,即最近的、最精确的元素節點)
- 目标階段(target phrase,目标節點上的事件觸發按代碼執行順序觸發)
- 冒泡階段(bubbling phrase,從目标節點到根節點 )
二、示範
<div>
<button>點選</button>
</div>
現在有一個div節點,div節點裡面有一個button節點。
let div = document.getElementsByTagName('div')[0];
div.addEventListener('click',(e)=>{
console.log('div')
})
let button = document.getElementsByTagName('button')[0];
button.addEventListener('click',(e)=>{
console.log('button')
})
現在我們隻看
div
節點和
button
節點,當我們點選
button
時會先後列印出
button
、
div
,因為
addEventListener
方法預設是讓事件在冒泡階段觸發。如果我們設定
addEventListener
第三個參數
useCapture
的值為
true
,就會讓事件在捕獲階段觸發:
div.addEventListener('click',(e)=>{
console.log('div')
},true)
或者
div.addEventListener('click',(e)=>{
console.log('div')
},{capture: true})
這個時候點選
button
就會先觸發
div
的
click
事件,再觸發
button
的
click
事件。
三、停止傳播:event.stopPropagation()
stopPropagation
方法會讓事件傳播到目标階段後停止傳播,是以也叫阻止冒泡。相當于讓事件流隻剩下捕獲階段和目标階段。是以下面的代碼會先後列印出
div1
、
button
。
button.addEventListener('click',(e)=>{
e.stopPropagation()
console.log('button')
})
div.addEventListener('click',(e)=>{
console.log('div1')
},true)
div.addEventListener('click',(e)=>{
console.log('div2')
})
四、馬上停止傳播:event.stopImmediatePropagation();
有個特例,如果目标階段的節點綁定了多個事件,它們不會區分捕獲和冒泡,事件觸發的順序為代碼執行的順序。
而且
event.stopPropagation()
在目标階段不會生效。如果目标階段有 a、b、c 三個觸發事件會按序執行,在 b 事件裡設定
event.stopPropagation()
并不會影響 c 事件的觸發。 但是如果在 b 事件裡設定
event.stopImmediatePropagation()
後 ,事件觸發到b之後就會停止觸發後面的所有事件。
更多關于DOM事件模型,推薦看阮一峰的教程