什么是事件冒泡
在一个对象上触发某类事件,如果此对象定义了此事件的处理程序,那么此事件就会调用这个处理程序,如果没有定义此事件处理程序或者事件返回true,那么这个事件会向这个对象的父级对象传播,从里到外,直至它被处理,或者它到达了对象层次的最顶层,即document或window对象。在一个页面上可以有多个事件,也可以有多个元素响应同一个事件,如:网页上有两个元素,其中一个元素嵌套在另一个元素里,并且都被绑定了 click 事件,同时 <body> 元素也绑定了 click 事件,当执行一次 click 事件时,将会触发三次响应,代码如下:
<div id="box">
外层div
<br>
<br>
<br>
<span>内层span</span>
<br>
<br>
<br>
外层div
</div>
<div id="msg"></div>
<script>
$(function(){
//为span元素绑定click事件
$("span").on("click",function(){
var txt = $("#msg").html() + "<p>内层span被点击</p>";
$("#msg").html(txt);
});
//为div元素绑定事件
$("#box").on("click",function(){
var txt = $("#msg").html() + "<p>外层div被点击</p>";
$("#msg").html(txt);
});
//为body元素绑定事件
$("body").on("click",function(){
var txt = $("#msg").html() + "<p>body被点击</p>";
$("#msg").html(txt);
});
})
</script>
页面效果如图:
当单击内部<span>元素,即触发<span>元素的click事件,会输出3条记录,如图:
只单击内部<span>就会触发外部<div>和<body>元素上绑定的click事件,这就是由事件冒泡所引起的。
只单击<span>元素的同时,也单击了包含<span>元素的元素<div>和包含<div>元素的元素元素<body>,并且每一个元素都会按照特定的顺序响应click事件。
元素的click事件会按照以下顺序“冒泡”:
- <span>
- <div>
- <body>
之所以称为冒泡,是因为事件会按照DOM的层次结构像水泡一样不断向上直至顶端,此列即为从<span>到<body>。
如何阻止事件冒泡
事件冒泡带来的问题
事件冒泡处理可能会激活我们本来不想激活的事件,导致程序错乱,甚至无从下手调试,这常成为对事件冒泡不熟悉程序员的棘手问题。如上例中,本只想触发<span>元素的click事件,然而<div>和<body>元素的click事件也同时被触发。因此,有必要对事件的作用范围进行限制。
- 事件对象
由于IE-DOM和标准DOM实现事件对象的方法各不相同,导致在不同浏览器中获取事件对象变得比较困难。针对这个问题,jQuery进行了必要的扩展和封装,从而使得在任何浏览器中能很轻松地获取事件对象以及事件对象的一些属性。如下,为函数添加一个函数便可使用事件对象:
$("#element").on("click",function(event){ //event : 事件对象
//...
})
这样,当单击“element”元素时,事件对象就被创建了。这个事件对象只有事件处理函数才能访问到,事件处理函数执行完毕后,事件对象也就被销毁了。
- 阻止事件冒泡
停止事件冒泡可以阻止事件中对其他对象的事件处理函数被执行。在jQuery中提供了 stopPropagation() 方法来停止事件冒泡。上例中代码可修改如下:
$("span").on("click",function(event){ //event : 事件对象
var txt = $("#msg").html() + "<p>内层span被点击</p>";
$("#msg").html(txt);
event.stopPropagation(); //停止事件冒泡
});
这样,当单击<span>元素时,只会触发该元素上的click事件。使用 stopPropagation() 方法同样可以阻止<div>上的事件冒泡问题。
- 阻止默认行为
网页中的元素有自己的默认行为,如点击超链接会跳转,“提交”按钮会提交表单,有事需要对这种默认行为进行阻止。
在jQuery中,提供了 preventDefault() 方法来阻止元素的默认行为。
看到这,你一定以为如果想同时对事件对象停止冒泡和默认行为,同时调用 stopPropagation() 和 preventDefault() 方法就可以了,当然,这种方法也没问题,但有一种简写方式:在事件处理函数中返回 false 即可。
event.stopPropagation(); //停止事件冒泡
改写为
return false;
事件捕获
事件捕获其实就是事件冒泡的相反过程,事件捕获是从最顶端往下开始触发。事件捕获是石子从水面落入水底,而事件冒泡是从水底打捞石子到水面。
遗憾的事,并非所有主流浏览器都支持事件捕获,并且jQuery不支持事件捕获,如果需要使用事件捕获,请直接使用原生JavaScript,本文不再解释。
学艺不精,难免有错误之处,如您发现有不能忍受的错误,请联系本人,将万分感激