前端–JavaScript 事件的三个阶段

1. addEventListener绑定事件

btn.addEventListener 绑定事件,只支持高版本的浏览器。

  1. 第一个参数:事件的类型,一个不带on的字符串类型的数据
  2. 第二个参数:事件处理函数
  3. 第三个参数: true,false.布尔类型的数据,false:事件冒泡 true:事件捕获。

btn.attachEvent();绑定事件,只支持ie10以及以下的版本。

  1. 当给同一个对象绑定多个相同事件的时候,ie8及以下,乱序的执行。
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
<button id="btn">按钮</button>
<script>
// onclick事件 同一个对象只能绑定一个事件触发的函数会覆盖。
// var btn=document.getElementById("btn");
// btn.onclick=function(){
// alert(1);
// };
// btn.onclick=function(){
// alert(2);
// }
function fn() {
alert(3);
}

function fn1() {
alert(4);
}

// 高版本浏览器支持,低版本浏览器,ie678不支持。
btn.addEventListener("click", fn, false);
btn.addEventListener("click", fn1, false);

// ie10及以下版本支持,ie8一下是乱序。
// btn.attachEvent("onclick",fn);
// btn.attachEvent("onclick",fn1);
</script>
1.1 兼容性封装绑定事件的函数
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
<button id="btn">按钮</button>
<script>
var btn = document.getElementById("btn");

function fn1() {
alert('哈');
}

addEvent(btn, "click", fn1, false);

/***
* 兼容性封装添加事件监听的函数。
* @param obj 待绑定的对象
* @param type 事件类型
* @param fn 事件处理函数
* @param bool false,true,是否冒泡
*/
function addEvent(obj, type, fn, bool) {
if (obj.addEventListener) {
obj.addEventListener(type, fn, bool)
} else {
obj.attachEvent("on" + type, fn);
}
}
</script>

2. 解绑事件类型

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
<button id="btn">按钮</button>
<script>
var btn = document.getElementById("btn");

//只能点一次
// btn.onclick=function(){
// alert(1);
// btn.onclick=null;
// }

//用匿名函数
// btn.addEventListener("click",function(){
// alert(123);
// },false);

function fn1() {
alert(1021);
}

// 解绑的方法
btn.addEventListener("click", fn1, false);
//btn.removeEventListener("click",fn1,false);

//btn.attachEvent("onclick", fn1);
// btn.detachEvent("onclick",fn1);
//removeEvent(btn, "click", fn1, false);

/***
* 兼容性封装解绑事件监听的函数。
* @param obj 待绑定的对象
* @param type 事件类型
* @param fn 事件处理函数
* @param bool false,true,是否冒泡
*/
function removeEvent(obj, type, fn, bool) {
if (obj.removeEventListener) {
obj.removeEventListener(type, fn, bool);
} else {
obj.detachEvent("on" + type, fn);
}
}
</script>

3. 事件冒泡

事件冒泡: 当嵌套元素,分别绑定的相同的事件类型,当触发某个元素的事件之后,会从当前该元素依次向外进行触发其他元素的相同的事件,这个过程就叫做冒泡。

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
53
54
55
56
57
58
59
60
61
62
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<title>事件冒泡</title>
<style>
#box1 {
width: 400px;
height: 400px;
background-color: #38ff7c;
}

#box2 {
width: 200px;
height: 200px;
background-color: #44ffec;
}

#box3 {
width: 100px;
height: 100px;
background-color: #a158ff;
}
</style>
</head>
<body>
<div id="box1">
<div id="box2">
<div id="box3">

</div>
</div>
</div>
<script>
var box1 = document.getElementById("box1");
var box2 = document.getElementById("box2");
var box3 = document.getElementById("box3");

box1.onclick = function () {
console.log("box1");
};
box2.onclick = function () {
console.log("box2");
};
box3.onclick = function () {
console.log("box3");
};
// document.body 获取body元素对象
document.body.onclick = function () {
console.log("body");
};
//document.documentElement 获取html元素对象
document.documentElement.onclick = function () {
console.log("html");
};
//window widnow对象。
window.onclick = function () {
console.log("window");
}
</script>
</body>
</html>

4. 事件的三个阶段☆

事件执行的过程:当触发某个元素的事件的时候,由外向内捕获到事件目标,在由内到外进行事件的冒泡。

事件三个阶段

  1. 第一个阶段: 事件捕获阶段:由外向内依次触发, 网景公司。
  2. 第二个阶段: 事件目标阶段: 被触发的元素。
  3. 第三个阶段: 事件冒泡阶段: 由内向外依次触发, 微软公司给ie定义的阶段。ie低版本只有事件的冒泡阶段。
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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<title>事件三个阶段</title>
<style>
#box1 {
width: 400px;
height: 400px;
background-color: #38ff7c;
}

#box2 {
width: 200px;
height: 200px;
background-color: #44ffec;
}

#box3 {
width: 100px;
height: 100px;
background-color: #a158ff;
}
</style>
</head>
<body>
<div id="box1">
<div id="box2">
<div id="box3">

</div>
</div>
</div>
<script>
var box1 = document.getElementById("box1");
var box2 = document.getElementById("box2");
var box3 = document.getElementById("box3");

// onclick 不能执行捕获阶段。
// box3.onclick = function (e) {
// console.log("box3");
// // 阻止冒泡
// e.stopPropagation();
// }
//
// box2.onclick = function () {
// console.log("box2");
// };
// box1.onclick = function () {
// console.log("box1");
// };

// false 执行事件的冒泡阶段, 如果是true的话,走的是捕获阶段。
// 捕获阶段会先输出box1,如果是走冒泡的话会先输出box3
box1.addEventListener("click", function () {
console.log("box1");
}, false);

box2.addEventListener("click", function (e) {
console.log("box2");
//取消冒泡
// e.stopPropagation();
}, false);

box3.addEventListener("click", function (e) {
console.log("box3");
console.log(e);
//取消冒泡
// e.stopPropagation();
}, false)

// ie老版本只有事件的冒泡阶段。
// box3.attachEvent("onclick", function () {
// console.log("box3");
// });
// box2.attachEvent("onclick", function () {
// console.log("box2");
// });
// box1.attachEvent("onclick", function () {
// console.log("box1");
// })
</script>
</body>
</html>

5. 事件委派机制(事件委托)

  1. 此时为了单击a删除,本来需要给每个a标签绑定一个单击事件,当a数量很大的时候,会造成内存占用过多,导致效率低下。解决方案:
  2. 事件委派:用的冒泡的原理,给ul添加一个单击事件,由于a和li都是ul的子元素,当单击任何的a标签和li标签,这个动作就会向外冒泡,最终都会触发ul的单击事件。通过e获取到MouseEvent, e.target 获取到真正单击的目标对象,再做相应的处理。
  3. 通过委派机制 父标签的添加的子元素 不需要重新绑定事件,会自动委派父标签去做。
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
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<title>事件委派机制(事件委托)</title>
<style>
ul, li {
list-style: none;
}
</style>
</head>
<body>
<div>
<ul id="list">
<li>01<a href="Javascript:void(0);">删除</a></li>
<li>02<a href="Javascript:void(0);">删除</a></li>
<li>03<a href="Javascript:void(0);">删除</a></li>
<li>04<a href="Javascript:void(0);">删除</a></li>
<li>05<a href="Javascript:void(0);">删除</a></li>
<li>06<a href="Javascript:void(0);">删除</a></li>
<li>07<a href="Javascript:void(0);">删除</a></li>
<li>08<a href="Javascript:void(0);">删除</a></li>
<li>09<a href="Javascript:void(0);">删除</a></li>
<li>10<a href="Javascript:void(0);">删除</a></li>
</ul>
</div>
<script>
//老办法
// var list = document.getElementById("list");
// var as = list.getElementsByTagName("a");
// for (var i = 0; i < as.length; i++) {
// as[i].onclick = function () {
// this.parentNode.parentNode.removeChild(this.parentNode);
// }
// }

//e:事件处理函数的参数对象。
var list = document.getElementById("list");
var num = 1;
list.onclick = function (e) {
var target = e.target;
target.parentNode.parentNode.removeChild(target.parentNode);
}
</script>
</body>
</html>