事件冒泡
事件冒泡: 子元素上触发事件时, 会触发父元素同样的事件
触发事件的 `当事人` : 事件参数中的 target 属性 -- 存储的是当事元素
代码片段:
<!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>事件冒泡</title>
<style>
#red{
background-color: red;
width: 500px;
height: 500px;
}
#green{
background-color: green;
width: 400px;
height: 400px;
}
#blue{
background-color: blue;
width: 300px;
height: 300px;
}
</style>
</head>
<body>
<div id="red">
<div id="green">
<div id="blue"></div>
</div>
</div>
<script>
red.onclick = function(e){
console.log('red click!');
console.log('触发本次事件的当事元素:', e.target);
}
green.onclick = function(e){
console.log('green click!');
console.log('触发本次事件的当事元素:', e.target);
}
blue.onclick = function(e){
console.log('blue click!');
console.log('触发本次事件的当事元素:', e.target);
}
</script>
</body>
</html>
样式就是这样的一个样式, 三个盒子嵌套, 当我们点击蓝色盒子时, 下面绿色盒子和红色盒子都会被触发的
可以看到, 点击蓝色盒子, 其它两个都会被触发, 当我们点击绿色盒子, 而红色盒子就会触发
那该怎么解决呢? DOM提供了这样的一个 stopPropagation 方法
停止冒泡: 父元素不会收到此次事件的通知
stop: 停止 propagation: 传播
把 stopPropagation 这个方法添加到蓝色盒子的脚本里面, 就不会影响其它两个啦
blue.onclick = function (e) {
console.log("blue click!");
console.log("触发本次事件的当事元素:", e.target);
e.stopPropagation();
};
都是触发自身的元素
事件委托
冒泡的应用场景: 委托
自己的事情 让别人帮忙处理; 此处 - 子元素的事情, 让父元素帮忙处理
然而最经典的例子就是 ul 和 li 了
下面来看这样的一个例子
点击谁, 谁高亮显示, 平常我们都是用forEach遍历 li 来显示的, 这里我们就来用事件委托的方式绑定 ul 来实现这样的效果, 先来准备 html 和 css 代码
<!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>事件委托</title>
<style>
ul {
display: flex;
margin: 0;
padding: 0;
list-style: none;
border: 1px solid gray;
}
li {
padding: 10px 20px;
background-color: #eee;
margin: 5px;
cursor: pointer;
}
.active {
background-color: orange;
color: white;
}
</style>
</head>
<body>
<ul>
<li>TheShy</li>
<li>Ning</li>
<li>Rookie</li>
<li>JackeyLove</li>
<li>BaoLan</li>
</ul>
</body>
</html>
这就是简简单单的 基础代码 这里就不必过多阐述了, 平常我们都是用下方这种方法来实现的
<script>
const lis = document.querySelectorAll('ul>li')
lis.forEach(li => li.onclick = function(){
lis.forEach(li => li.classList.remove('active'))
this.classList.add('active')
})
</script>
然后这种方式的缺点就是: 需要为每个 li 绑定单独的方法, 然而来看下方的委托方式
<script>
const ul = document.querySelector("ul");
ul.onclick = function (e) {
console.log("ul click!");
console.log("当事元素:", e.target);
console.dir(e.target);
if (e.target.localName == "li") {
e.target.classList.add("active");
}
};
</script>
这里呢首先把 li 的父元素 ul 找到, 然后绑定一个点击事件, 通过 冒泡的 方式接收事件的 `当事人`, 这里就是说的当事元素, 然后通过打印可以点击一下, 查找一下我们所需要的方式都有哪些
通过查找我们看到, 一共呢找到了三种, 一个是 localName 与 nodeName 与 tagName, 这三个方法, 这三个方法用哪个都可以, 我这边用的是localName, 因为平时都是用这个方法, 换其它的还有点不自在, 最终通过if判断来执行点击谁, 把 active 添加到谁身上就可以了;
好了, 今天就到这里了 O(∩_∩)O