什么是事件流?
当页面元素触发事件的时候,该元素的容器以及整个页面都会按照特定顺序响应该元素的触发事件,事件传播的顺序就叫做事件流。
事件流分类:
捕获阶段
当一个元素的事件被触发时,会从DOM的根元素开始依次调用同名事件 ( 从外到里或从父到子 )
语法格式:
dom.addEventListener( 事件类型,时间处理函数,是否使用捕获机制)
第三个参数为true表示捕获阶段触发,false表示冒泡阶段触发,默认值为false
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.skyblue{
width: 200px;
height: 200px;
background-color: skyblue;
}
.pink{
width: 150px;
height: 150px;
background-color: pink;
transform: translate(15%,15%);
}
.gold{
width: 100px;
height: 100px;
background-color: gold;
transform: translate(25%,25%);
}
.palegreen{
width: 50px;
height: 50px;
background-color: palegreen;
transform: translate(50%,50%);
}
</style>
</head>
<body>
<div class="skyblue">
<div class="pink">
<div class="gold">
<div class="palegreen"></div>
</div>
</div>
</div>
<script>
const skyblue = document.querySelector('.skyblue');
const pink = document.querySelector('.pink');
const gold = document.querySelector('.gold');
const palegreen = document.querySelector('.palegreen');
skyblue.addEventListener("click", function () {
console.log("skyblue");
},true)
pink.addEventListener("click", function () {
console.log("pink");
},true)
gold.addEventListener("click", function () {
console.log("gold");
},true)
palegreen.addEventListener("click", function (e) {
console.log("palegreen");
},true)
</script>
</body>
</html>
只点击绿色盒子,最后函数执行顺序:蓝,粉,黄,绿,即事件捕获的顺序。
冒泡阶段
当一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发 。这一过程被称为事件冒泡。 简单理解:当一个元素触发事件后,会依次向上调用所有父级元素的同名事件(从里到外或从子到父)
事件冒泡是 默认存在的,(addEventListener ) 第三个参数默认是传入 false ,都是冒泡
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.skyblue{
width: 200px;
height: 200px;
background-color: skyblue;
}
.pink{
width: 150px;
height: 150px;
background-color: pink;
transform: translate(15%,15%);
}
.gold{
width: 100px;
height: 100px;
background-color: gold;
transform: translate(25%,25%);
}
.palegreen{
width: 50px;
height: 50px;
background-color: palegreen;
transform: translate(50%,50%);
}
</style>
</head>
<body>
<div class="skyblue">
<div class="pink">
<div class="gold">
<div class="palegreen"></div>
</div>
</div>
</div>
<script>
const skyblue = document.querySelector('.skyblue');
const pink = document.querySelector('.pink');
const gold = document.querySelector('.gold');
const palegreen = document.querySelector('.palegreen');
skyblue.addEventListener("click", function () {
console.log("skyblue");
})
pink.addEventListener("click", function () {
console.log("pink");
})
gold.addEventListener("click", function () {
console.log("gold");
})
palegreen.addEventListener("click", function (e) {
console.log("palegreen");
})
</script>
</body>
</html>
只点击绿色盒子,最后函数执行顺序:绿,黄,粉,蓝,即事件冒泡的顺序。
阻止冒泡
如果不想要其带来的影响,由于addEventListener默认在事件冒泡阶段执行,那么就需要阻止事件冒泡的发生,称为阻止冒泡。阻止冒泡是指阻断事件的流动,保证事件只在当前元素被执行,而不再去影响到其对应的祖先元素。
事件对象.stopPropagation()
这个函数可以阻断事件流动传播,对事件冒泡和事件捕获都有效果。
skyblue.addEventListener("click", function () {
console.log("skyblue");
})
pink.addEventListener("click", function () {
console.log("pink");
})
gold.addEventListener("click", function () {
console.log("gold");
})
palegreen.addEventListener("click", function (e) {
console.log("palegreen");
e.stopPropagation()
})
只点击绿色盒子,只有绿色盒子执行了事件监听,其它盒子由于事件冒泡被阻断了,没有接收到绿色盒子的冒泡。当时间冒泡触发时,被绿色盒子的stopPropagation截断了,就不再往上冒泡,触发祖先的函数了。
事件委托
事件委托是利用事件流的特征解决一些现实开发需求的知识技巧,主要的作用是提升程序效率,大量的事件监听是比较耗费性能的。
事件对象. target. tagName 可以获得真正触发事件的元素
此外e.target.tagName存储着触发元素的元素名,不过是大写的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.skyblue{
width: 200px;
height: 200px;
background-color:skyblue;
display: flex;
justify-content:space-around;
align-items: center;
}
.pink{
width: 50px;
height: 50px;
background-color: pink;
list-style: none;
}
.gold{
width: 50px;
height: 50px;
background-color: gold;
list-style: none;
}
.palegreen{
width: 50px;
height: 50px;
background-color: palegreen;
list-style: none;
}
</style>
</head>
<body>
<ul class="skyblue">
<li class="pink"></li>
<li class="gold"></li>
<li class="palegreen"></li>
</ul>
<script>
const skyblue = document.querySelector(".skyblue");
skyblue.addEventListener("click", function (e) {
console.log(e.target.tagName);
})
</script>
</body>
</html>
要让三个子级盒子被点击后,都会变成白色
skyblue.addEventListener("click", function (e) {
if (e.target.tagName === "LI")
{
e.target.style.backgroundColor = "#ffffff";
}
})