DOM事件流
事件流描述的是从页面中接收事件的顺序。
事件发生时,会在元素节点之间按照特定的顺序传播,这个传播过程称为DOM事件流。
图源:DOM的默认事件、事件模型、事件委托、阻止默认事件、冒泡事件的方式等。
DOM事件流分为3个阶段:
1.捕获阶段 :从上往下(当前目标阶段)、从大往小(当前目标阶段)这种传播过程我们称为捕获阶段
2.当前目标阶段
3.冒泡阶段:从小往大、从里往外这种传播过程我们称为冒泡阶段
※ 事件冒泡:IE最早提出,事件开始有最具体的元素接收,然后逐级向上传播到DOM最顶层节点的过程。
※ 事件捕获:网景最早提出,由DOM最顶层节点开始,然后逐级向下传播到最具体的元素接收的过程。
注意
1.js代码中只能执行捕获或者冒泡其中一个阶段。
2.onclick和attachEvent(IE9以下使用)只能得到冒泡阶段。因为它两是IE所有的
3.element.addEventListener(event, function, {, useCapture}) 第三个参数如果是true,表示在事件捕获阶段调用事件处理程序;如果是false(默认不写就是false),表示在事件冒泡阶段调用事件处理程序。
addEventListener事件捕获阶段示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>11-DOM事件流三个阶段</title>
<style>
.father {
margin: 100px auto;
width: 300px;
height: 300px;
background-color: blueviolet;
overflow: hidden;
text-align: center;
}
.son {
width: 150px;
height: 150px;
background-color: pink;
line-height: 200px;
margin: 50px;
}
</style>
</head>
<body>
<div class="father">
<div class="son">son盒子</div>
</div>
<script>
// 获取两个div
var father = document.querySelector('.father')
var son = document.querySelector('.son')
// 注意addEventListener的第三个参数为true时开启捕获阶段
father.addEventListener('click', function(){
alert('father')
},true)
son.addEventListener('click', function(){
alert('son')
},true)
document.addEventListener('click', function(){
alert('document')
},true)
</script>
</body>
</html>
捕获阶段运行效果:
此程序执行处理 当点击son盒子时 document -> html -> body -> father -> son
当点击father盒子时 document -> html -> body -> father
因为其他的没有绑定事件所以在页面上不体现出现。但顺序是这样的
addEventListener事件冒泡阶段示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>11-DOM事件流三个阶段</title>
<style>
.father {
margin: 100px auto;
width: 300px;
height: 300px;
background-color: blueviolet;
overflow: hidden;
text-align: center;
}
.son {
width: 150px;
height: 150px;
background-color: pink;
line-height: 200px;
margin: 50px;
}
</style>
</head>
<body>
<div class="father">
<div class="son">son盒子</div>
</div>
<script>
var father = document.querySelector('.father')
var son = document.querySelector('.son')
// addEventListener 第三个可选参数默认是false,执行冒泡
father.addEventListener('click', function(){
alert('father')
})
son.addEventListener('click', function(){
alert('son')
})
document.addEventListener('click', function(){
alert('document')
})
</script>
</body>
</html>
冒泡阶段运行效果:
此程序执行处理 当点击son盒子时 son-> father -> body -> html -> document
当点击father盒子时 father -> body -> html -> document
4.实际开发中,我们很少使用事件捕获,我们更多关注事件冒泡。
5.有些事件是没有冒泡的:onblur、onfocus、onmouseenter、onmouseleave…。
6.事件冒泡有时候会带来麻烦,有时候又会帮助很巧妙的做某些事