问题出现的场景是,父元素和子元素使用同样的事件(点击)然后点击触发会两个都触发,如果只想用触发父元素呢 或者如果只想触发子元素呢?
事件详解
事件绑定方式
直接在元素上绑定 <div οnclick="fun()">
通过元素赋值的方法绑定
div.onclick = function(){}
通过监听器的方式绑定
const div = document.querySelector("div")
div.addEventListener("click",function(){},true/false);
addEventListener("事件名称","执行函数“,"事件机制”)
事件机制默认false即 忽略什么都不填
事件流
这个问题需要了解一下事件流
事件流就是事件在DOM树中传播的过程中,一个传播执行的顺序
过程:事件捕获阶段,目标阶段,事件冒泡阶段
事件流分为捕获事件流和冒泡事件流
捕获事件流:事件从目标元素向根节点传播的过程
冒泡事件流:事件从根节点向目标元素传播的过程
事件机制
冒泡:元素嵌套时,外层元素和内层元素存在相同的事件,那么事件会从内向外依次触发
- true:捕获机制
- false:冒泡机制
捕获:元素嵌套时,外层元素和内层元素存在相同事件,由外到内依次触发
阻止事件流
- 阻止冒泡
e.stopPropagation():阻止事件传播 (同样也是阻止冒泡)
- 阻止默认行为
e.preventDefault()
<!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>
.outer {
width: 500px;
height: 500px;
border: 1px solid;
background-color: red;
}
.inner {
width: 200px;
height: 300px;
border: 1px solid white;
background-color: aqua;
}
</style>
</head>
<body>
<div class="outer">div2
<div class="inner">div1</div>
</div>
<script>
const outer = document.getElementsByClassName("outer")[0];
const inner = document.getElementsByClassName("inner")[0];
// 添加事件监听器
outer.addEventListener('click', function (e) {
console.log("outer 的捕获 监听器被触发");
// e.stopPropagation(); //
}, true);
outer.addEventListener('click', function (e) {
console.log("outer 的冒泡监听器被触发");
// e.stopPropagation();
}, false);
inner.addEventListener('click', function (e) {
console.log("inner 的捕获监听器被触发");
// e.stopPropagation();
}, true);
inner.addEventListener('click', function (e) {
console.log("inner 的冒泡捕获监听器被触发");
// e.stopPropagation();
}, false);
</script>
</body>
</html>
可以用这个自测一下,这是最初的样子
当在outer捕获的监听器里加上 e.stopPropagation();
补充一下 这个e 是事件对象event 是监听器在执行回调函数中的第一个参数,事件对象
-
事件在捕获阶段被 outer 捕获后,stopPropagation() 阻止了事件继续向下传播(不会到达 inner)。
-
因此,inner 的捕获和冒泡监听器都不会触发,outer 的冒泡监听器也不会触发。
第二个是outer冒泡监听器添加 e.stopPropagation();
-
事件会正常完成捕获阶段和目标阶段(inner 的监听器会触发)。
-
在冒泡阶段,事件到达 outer 的冒泡监听器时被阻止,但此时事件已经完成了目标阶段的传播。
-
stopPropagation() 在冒泡阶段的作用是阻止事件继续向上传播(例如,阻止父元素的冒泡监听器),但对捕获阶段无影响。
然后给inner的捕获监听器加上阻止传播方法,
-
事件在捕获阶段会依次触发 outer 和 inner 的捕获监听器。
-
在 inner 的捕获监听器中调用 stopPropagation() 会阻止事件继续向下传播(虽然已经到达目标,但不会触发目标阶段的冒泡监听器)。
-
因此,inner 的冒泡监听器和 outer 的冒泡监听器都不会触发。
,
最后给inner的冒泡添加阻止
-
事件会正常完成捕获阶段和目标阶段。
-
在 inner 的冒泡监听器中调用 stopPropagation() 会阻止事件继续向上冒泡(outer 的冒泡监听器不会触发)。
总结
stopPropagation()的作用
首先确实都是阻止事件进一步传播
在捕获阶段调用时,会阻止事件向下传播到目标
在冒泡阶段调用时,会阻止事件向上传播到父元素
事件流是 捕获阶段-》目标阶段-》冒泡阶段
且捕获阶段是从外到内
目标阶段:触发目标元素的监听器(按注册顺序,先捕获后冒泡)
冒泡阶段是从内到外
回归问题
冒泡阶段的 stopPropagation() 可阻止父元素触发。
捕获阶段的 stopPropagation() 可阻止子元素触发
差不多测试完就明白 事件冒泡的原理了 然后再阻止……
评论前必须登录!
注册