在一个对象上触发某类事件(比如单击onclick事件),如果此对象定义了此事件的处理程序,那么此事件就会调用这个处理程序,如果没有定义此事件处理程序或者事件返回true,那么这个事件会向这个对象的父级对象传播,从里到外,直至它被处理(父级对象所有同类事件都将被激活),或者它到达了对象层次的最顶层,即document对象(有些浏览器是window)。
事件冒泡允许多个操作被集中处理(把事件处理器添加到一个父级元素上,避免把事件处理器添加到多个子级元素上),它还可以让你在对象层的不同级别捕获事件。
事件冒泡的示例
编写三个嵌套的div,同时绑定click事件,来演示事件冒泡。
只点击了一次.son
的div
,弹出了son
的alert()
,然后继续弹出father()
,grandfather()
的弹出框。
只单单点击了一次黄色的div,但是却弹出了三个alert(),这种就如同冒泡一样,逐个从底部元素传递到上级的元素。
但是也有一个疑问,那就是会不会是因为黄色div的位置,在这三个div重叠的问题,会不会点击了黄色div也包含点击下面两个div呢?
可以编写一个偏移问题后的div来看看,如下:
好了,现在黄色的div已经跟两个父级的元素位置不重叠了。再次点击看看,如下:
事件冒泡示例的结论
可以看出点击黄色div,依然会依次弹出三个alert()。说明这个click()事件的传递并不是根据点击位置,而是根据html元素的嵌套。
<div class="grandfather">
<div class="father">
<div class="son"></div>
</div>
</div>
事件冒泡机制有时候是不需要的,需要阻止掉,通过 event.stopPropagation()
来阻止
阻止上面点击黄色div的click()冒泡传递
设置了阻止冒泡传递之后,那么click()
事件就不会传递到father
和grandfather
的事件,所以只有一个alert()
弹出。
<!DOCTYPE html>
<html>
<head>
<title></title>
<script type="text/javascript" src="jquery-3.4.0.min.js"></script>
<script type="text/javascript">
$(function(){
$('.son').click(function(event){
alert('son');
// 阻止冒泡
event.stopPropagation();
})
$('.father').click(function(){
alert('father');
})
$('.grandfather').click(function(){
alert('grandfather');
})
})
</script>
<style type="text/css">
.grandfather{
width: 300px;
height: 300px;
background-color: green;
position: relative;
}
.father{
width: 200px;
height: 200px;
background-color: pink;
}
.son{
width: 100px;
height: 100px;
background-color: gold;
position: absolute;
top: 400px;
}
</style>
</head>
<body>
<!-- .grandfather>.father>.son -->
<div class="grandfather">
<div class="father">
<div class="son"></div>
</div>
</div>
</body>
</html>
下面来看看一个比较简单的阻止冒泡的写法。
阻止表单提交
$('#form1').submit(function(event){
event.preventDefault();
})
这个是阻止表单提交的默认行为,这个行为和阻止冒泡可以合并一起写,如下。
实际开发中,一般把阻止冒泡和阻止默认行为合并起来写,合并写法可以用
// event.stopPropagation();
// event.preventDefault();
// 合并写法:
return false;
好,下面将阻止事件冒泡的方法写成return false;
来看看。
使用return false;
其实就是使函数传递false的值,从而阻止冒泡传递,阻止函数继续执行。