DOM 结构是一个树形结构,当一个 HTML元素触发一个事件时,该事件会在元素节点和根节点之间的路径传播,路径所经过的节点都会收到该事件,这个过程称为 DOM 事件流。
具体过程见下图:
捕获阶段
从根节点到目标节点,找到触发事件的节点。
IE中的事件模型没有捕获阶段,只有冒泡阶段
目标阶段
触发目标 节点上的事件,按代码执行顺序触发
冒泡阶段
从目标节点到跟节点
focus 和 blur 不支持冒泡
事件注册
DOM
<div>
<button>点击</button>
</div>
添加事件
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')
})
而且event.stopPropagation()在目标阶段不会生效。如果目标阶段有 a、b、c 三个触发事件会按序执行,在 b 事件里设置event.stopPropagation()并不会影响 c 事件的触发。 但是如果在 b 事件里设置event.stopImmediatePropagation()后 ,事件触发到b之后就会停止触发后面的所有事件,并且不再冒泡。
参考:
事件流、事件冒泡
事件流、事件冒泡的表现行为
当触发一个 HTML 元素的事件时,事件会在该元素和根元素之间传播。传播分为三个阶段:
定义
DOM 结构是一个树形结构,当一个 HTML元素触发一个事件时,该事件会在元素节点和根节点之间的路径传播,路径所经过的节点都会收到该事件,这个过程称为 DOM 事件流。
具体过程见下图:
捕获阶段
从根节点到目标节点,找到触发事件的节点。
IE中的事件模型没有捕获阶段,只有冒泡阶段
目标阶段
触发目标 节点上的事件,按代码执行顺序触发
冒泡阶段
从目标节点到跟节点
focus 和 blur 不支持冒泡
事件注册
DOM
添加事件
点击
button
时会先后打印出 button、div,因为addEventListener方法默认是让事件在冒泡阶段触发。如果我们设置addEventListener第三个参数useCapture的值为true,就会让事件在捕获阶段触发:这个时候点击button就会先触发div的click事件,再触发button的click事件。
停止传播:event.stopPropagation()
stopPropagation
方法会让事件传播到目标阶段后停止传播,目标阶段不受限制,后边的事件都不会再执行,所以也叫阻止冒泡。相当于让事件流只剩下捕获阶段和目标阶段。所以下面的代码会先后打印出 div1、 button 。马上停止传播:event.stopImmediatePropagation();
有个特例,如果目标阶段的节点绑定了多个事件,它们不会区分捕获和冒泡,事件触发的顺序为代码执行的顺序。
而且event.stopPropagation()在目标阶段不会生效。如果目标阶段有 a、b、c 三个触发事件会按序执行,在 b 事件里设置event.stopPropagation()并不会影响 c 事件的触发。 但是如果在 b 事件里设置event.stopImmediatePropagation()后 ,事件触发到b之后就会停止触发后面的所有事件,并且不再冒泡。