DOM事件流和事件对象

DOM事件流

事件流描述的是从页面中接收事件的顺序
事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流
DOM事件流分为3个阶段:
1.捕获阶段
2.当前目标阶段
3.冒泡阶段

事件捕获

事件捕获:网景最早提出,由DOM最顶层节点开始,然后逐级向下传播到具体的元素接受的过程

事件冒泡

事件冒泡:IE最早提出,事件开始由最具体的元素接收,然后逐级向上传播到DOM最顶层节点的过程

注意:
1.JS代码中只能执行捕获或者冒泡其中的一个阶段
2.onclick和attachEvent只能得到冒泡阶段
3.addEventListener(type,listener,[useCapture])第三个参数如果是true,表示在事件捕获阶段调用事件处理程序;如果是false(不写默认是false),表示在事件冒泡阶段调用事件处理程序
4.实际开发中我们很少使用事件捕获,我们更关注事件冒泡
5.有些事件是没有冒泡的,比如 onblur、onfocus、onmouseenter、onmouseleave

事件对象

1.event 就是一个事件对象 写到我们侦听函数的
2.事件对象只有有了事件才会存在,它是系统给我们自动创建的,不需要我们传递参数
3.事件对象是我们事件一系列相关数据的集合 跟事件相关的 比如鼠标点击里面就包含了鼠标的相关信息,鼠标坐标,如果是键盘事件里面就包含了键盘事件的信息 比如 判断用户按下了哪个键

事件对象的常见属性和方法

阻止事件捕获和事件冒泡

有时候我们并不希望事件捕获或事件冒泡,可以用事件对象中的方法:

1
2
e.stopPropagation();
e.stopImmediatePropagation();

阻止事件捕获和冒泡

它们的区别是:如果在其中一个事件监听器中执行 stopImmediatePropagation() ,那么剩下的事件监听器都不会被调用:

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<!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>Document</title>
<style>
.father {
display: flex;
justify-content: center;
align-items: center;
width: 300px;
height: 300px;
background-color: #bfa;
margin: 100px auto;
}

.son {
width: 150px;
height: 150px;
background-color: pink;
}
</style>
</head>

<body>
<div class="father">
<div class="son"></div>
</div>
<script>
var father = document.querySelector('.father');
var son = document.querySelector('.son');
son.addEventListener('click', function (e) {
console.log('我是 son 元素上被绑定的第一个监听函数');
}, true);
son.addEventListener('click', function (e) {
console.log('我是 son 元素上被绑定的第二个监听函数');
}, true);
father.addEventListener('click', function (e) {
console.log('我是 father 元素上被绑定的第一个监听函数');
// 阻止事件捕获和冒泡
e.stopPropagation();
}, true);
father.addEventListener('click', function (e) {
console.log('我是 father 元素上被绑定的第二个监听函数');
}, true);
</script>
</body>
</html>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<!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>Document</title>
<style>
.father {
display: flex;
justify-content: center;
align-items: center;
width: 300px;
height: 300px;
background-color: #bfa;
margin: 100px auto;
}

.son {
width: 150px;
height: 150px;
background-color: pink;
}
</style>
</head>

<body>
<div class="father">
<div class="son"></div>
</div>
<script>
var father = document.querySelector('.father');
var son = document.querySelector('.son');
son.addEventListener('click', function (e) {
console.log('我是 son 元素上被绑定的第一个监听函数');
}, true);
son.addEventListener('click', function (e) {
console.log('我是 son 元素上被绑定的第二个监听函数');
}, true);
father.addEventListener('click', function (e) {
console.log('我是 father 元素上被绑定的第一个监听函数');
// 阻止事件捕获和冒泡
// e.stopPropagation();
e.stopImmediatePropagation();
}, true);
father.addEventListener('click', function (e) {
console.log('我是 father 元素上被绑定的第二个监听函数');
}, true);
</script>
</body>
</html>