在说明事件冒泡与事件捕获之前,我们先来聊一聊addEventListener() 中的e.target和this的区别。
this: 返回的是绑定事件的对象(元素),例如,哪个元素绑定了这个点击事件
e.target:返回的是触发事件的元素,例如,点击了哪个元素,就返回那个元素。
事件冒泡
微软提出了名为事件冒泡(event bubbling)的事件流。事件冒泡可以形象地比喻为把一颗石头投入水中,泡泡会一直从水底冒出水面。也就是说,事件会从最内层的元素开始发生,一直向上传播,直到document对象。
<div id="outer">
<p id="inner">Click me!</p>
</div>
p -> div -> body -> html -> document
事件委托
网景提出另一种事件流名为事件捕获(event capturing)。与事件冒泡相反,事件会从最外层开始发生,直到最具体的元素。
上面的例子在事件捕获的概念下发生click事件的顺序应该是
document -> html -> body -> div -> p
过程图:
所以1-3是捕获过程,3-4是目标阶段,4-7是冒泡阶段;
所以有一道常见笔试题:问捕获,冒泡与冒泡的顺序是?
答案:捕获---->目标------>冒泡
如何开启冒泡与捕获?
通过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>Document</title>
<style>
#outer {
width: 200px;
height: 200px;
background-color: salmon;
}
#outer p {
background-color: seagreen;
}
</style>
</head>
<body>
<div id="outer">
<p id="inner1">
子盒子1
<p id="inner2">
子盒子2
<p id="inner3">
子盒子3
</p>
</p>
</p>
</div>
</body>
<script>
let inner1 = document.querySelector('#inner1')
let inner2 = document.querySelector('#inner2')
let inner3 = document.querySelector('#inner3')
let outer = document.querySelector('#outer')
inner3.addEventListener('click',function(e){
console.log('子盒子3被点击了');
})
outer.addEventListener('click',function(e){
console.log('当前的e.target是'+ e.target.innerHTML);
},false) //在冒泡阶段执行
</script>
</html>
效果:
应用:
事件代理(事件委托)
点击每个li就让哪个li改变成对应的颜色。以前就是需要给每个li注册事件,是非常辛苦的,而且访问DOM的次数越多,这就会延长整个页面的交互就绪的事件。
<!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>
.color_list {
display: flex;
display: -webkit-flex;
}
.color_list li {
width: 100px;
height: 100px;
list-style: none;
text-align: center;
line-height: 100px;
}
.box {
width: 600px;
height: 150px;
background-color: #cccccc;
line-height: 150px;
text-align: center;
}
</style>
</head>
<body>
<ul class="color_list">
<li>red</li>
<li>orange</li>
<li>yellow</li>
<li>green</li>
<li>blue</li>
<li>purple</li>
</ul>
<script>
var color_list = document.querySelector(".color_list");
var colors = color_list.getElementsByTagName("li");
/* 未使用事件代理 */
for(let i = 0;i < colors.length;i++){
colors[i].addEventListener('click',function(e){
this.style.backgroundColor= e.target.innerHTML
},false)
}
/*
使用事件代理
color_list.addEventListener('click', function (e) {
if (e.target.nodeName.toLowerCase() === "li") {
e.target.style.backgroundColor= e.target.innerHTML
}
},false) */
</script>
</body>
</html>