在学习阻止事件冒泡时,我们思考一个问题:
addEventListener的第三个参数为true是阻止事件传递还是false?
答案:都不会阻止事件传递,因为true捕获阶段触发 false冒泡阶段触发;要阻止事件传递 唯一的方式就是阻止事件冒泡:事件对象调用stopPropagation()
直接代码说明:
<style>
body{
margin: 0px;
}
.box1 {
width: 400px;
height: 300px;
background-color: brown;
cursor: pointer;
position: relative;
left: 100px;
top: 20px;
}
.box2{
width: 200px;
height: 200px;
background-color: red;
cursor: pointer;
position: absolute;
left: 500px;
top: 20px;
}
.box3{
width: 100px;
height: 100px;
background-color: gold;
cursor: pointer;
margin: 10px;
padding: 5px;
border: 3px solid saddlebrown;
}
</style>
<div class='box1'>
<div class="box2">
<div class="box3">
</div>
</div>
</div>
<script>
//addEventListener第三个参数 true捕获阶段触发 false冒泡阶段触发
var box1=document.querySelector(".box1")
var box2=document.querySelector(".box2")
var box3=document.querySelector(".box3")
box1.addEventListener("click",(e)=>{
console.log("box111111111a",e)
},false)
box2.addEventListener("click",(e)=>{
console.log("box22222")
},false)
box3.addEventListener("click",(e)=>{
// 阻止事件冒泡
e.stopPropagation()
console.log("box33333")
})
</script>
运行结果:
点击box3,可以看到只有 box3触发了,因为box1,box2是在冒泡阶段触发,然而在box3事件对象中调用了stopPropagation(),阻止了事件冒泡,所以box1,box2的事件不再触发。
注意:只能阻止冒泡阶段,不能阻止捕获阶段。
把上述例子的box1的addEventListener监听器的第三个参数改为true看一下
<style>
body{
margin: 0px;
}
.box1 {
width: 400px;
height: 300px;
background-color: brown;
cursor: pointer;
position: relative;
left: 100px;
top: 20px;
}
.box2{
width: 200px;
height: 200px;
background-color: red;
cursor: pointer;
position: absolute;
left: 500px;
top: 20px;
}
.box3{
width: 100px;
height: 100px;
background-color: gold;
cursor: pointer;
margin: 10px;
padding: 5px;
border: 3px solid saddlebrown;
}
</style>
<div class='box1'>
<div class="box2">
<div class="box3">
</div>
</div>
</div>
<script>
//addEventListener第三个参数 true捕获阶段触发 false冒泡阶段触发
var box1=document.querySelector(".box1")
var box2=document.querySelector(".box2")
var box3=document.querySelector(".box3")
box1.addEventListener("click",(e)=>{
console.log("box111111111a",e)
},true)
box2.addEventListener("click",(e)=>{
console.log("box22222")
},false)
box3.addEventListener("click",(e)=>{
// 阻止事件冒泡
e.stopPropagation()
console.log("box33333")
})
</script>
运行结果:
点击box3,可以看到box1和box3的事件触发了,但是box2没有触发,所以捕获阶段的传递是不能影响的。
阻止事件冒泡还有一个方法stopImmediatePropagation(),这个方法不仅会阻止向祖元素的冒泡,还会阻止同一个节点上同一事件的其他的事件处理程序。
上述代码修改一下,给box3再添加一个点击事件。
<style>
body{
margin: 0px;
}
.box1 {
width: 400px;
height: 300px;
background-color: brown;
cursor: pointer;
position: relative;
left: 100px;
top: 20px;
}
.box2{
width: 200px;
height: 200px;
background-color: red;
cursor: pointer;
position: absolute;
left: 500px;
top: 20px;
}
.box3{
width: 100px;
height: 100px;
background-color: gold;
cursor: pointer;
margin: 10px;
padding: 5px;
border: 3px solid saddlebrown;
}
</style>
<div class='box1'>
<div class="box2">
<div class="box3">
</div>
</div>
</div>
<script>
//addEventListener第三个参数 true捕获阶段触发 false冒泡阶段触发
var box1=document.querySelector(".box1")
var box2=document.querySelector(".box2")
var box3=document.querySelector(".box3")
box1.addEventListener("click",(e)=>{
console.log("box111111111a",e)
},true)
box2.addEventListener("click",(e)=>{
console.log("box22222")
},false)
box3.addEventListener("click",(e)=>{
// 阻止事件冒泡
e.stopImmediatePropagation()
console.log("box33333")
})
box3.addEventListener("click",(e)=>{
console.log("box33333bbb")
})
</script>
运行结果:
可见并没有打印box33333bbb,所以证明stopImmediatePropagation()阻止了同一个节点上同一事件的其他的事件处理程序
特殊的IE浏览器,采用cancelBubble()方法阻止冒泡,event.cancelBubble=true时,阻止事件冒泡 适用于ie8及ie8以下。
默认事件
官方为我们提供了许多默认的事件,如表单提交,a标签跳转,右键菜单等等。
对于默认事件我们不能通过stopPropagation()来取消它的触发,为此官方提供了一个专属的方法 preventDefault()。
写一个小例子:针对于a标签的链接跳转
<a href="http://www.baidu.com" id="a1">baidu</a>
<script>
var a1=document.getElementById("a1")
a1.addEventListener("click",(e)=>{
console.log(66666)
//阻止系统默认事件
e.preventDefault()//可以阻止默认事件
})
</script>
运行后控制台打印66666,不会再跳转到百度首页。
特殊的IE:event.returnValue=false才能阻止默认事件。