概述
js事件在触发时会在元素节点之间按照特定的顺序进行传播,这个传播的过程就是 DOM 事件流。
例如:给页面中的一个 button 按钮注册了点击事件并进行了点击,因为 button 在 body 标签内部所以当点击了 button 时也就点击了 body;body 又在 html 内部,所以就点击了html;html 在 doucment 文档中也就点击了document。
两种事件流
-
冒泡事件流
由 IE 最早提出,从目标元素开始,然后一层一层向外接收事件并响应
-
捕获事件流
最早由网景提出,从最外层开始,然后一层一层向内接收事件并响应
DOM 事件流的三个阶段
捕获阶段
从最顶层的节点开始逐层向下传播(从外到里)直到具体的目标元素的过程(从最不具体的对象到触发事件的目标对象的过程)。
目标阶段
事件对象到达事件目标
冒泡阶段
当事件被触发后这个事件就会逐层向上传播(从里到外)直到最顶层的 DOM 节点的过程。
设置执行阶段
JS 代码只能执行冒泡阶段或捕获阶段其中的一个阶段;通过 on
前缀和 attachEvent()
注册的事件只能获取冒泡阶段;通过 addEventLIstener()
方法的第三个参数可以设置事件的执行阶段,为 true 时捕获阶段执行,为 false 时冒泡阶段执行。
捕获阶段:
<div id="dv1">
<div id="dv2">
<div id="dv3"></div>
</div>
</div>
<script>
function my$(id){
return document.getElementById(id);
}
//事件有三个阶段:
/*
1.事件捕获阶段 :从外向内
2.事件目标阶段 :最开始选择的那个
3.事件冒泡阶段 : 从里向外
*/
// 获取页面元素
var arr = [my$('dv1'),my$('dv2'),my$('dv3')];
// 为每个元素注册相同的事件
arr.forEach(function(item){
//第三个参数控制事件的阶段,false 为冒泡阶段(由内到外),true 为捕获阶段(由外到内)
item.addEventListener('click',function(e){
// 事件处理函数有一个默认的事件对象 e;
// 通过 e.eventPhase 可返回事件阶段;1为捕获阶段,2为目标阶段,3为冒泡阶段
alert(this.id +'事件阶段:'+ e.eventPhase);
},true); // 捕获阶段执行
});
</script>
CSS:
#dv1 {
width: 300px;
height: 200px;
background: red;
}
#dv2 {
width: 250px;
height: 150px;
background: green;
}
#dv3 {
width: 200px;
height: 100px;
background: blue;
}
冒泡阶段:
将第三个参数改为 fasle 或省略即可
补充:并不是所有的事件都有冒泡,例如:onfocus
、onblur
、onmouseenter
、onmouseleave