冒泡型事件:
事件按照从最特定的 事件目标到最不特定的事件目标 (document对象)的顺序触发。
捕获型事件:
事件从最不精确的对象(document 对象)开始触发,然后到最精确。(也可以在窗口级别捕获 事件,不过必须由开发人员特别指定)。
支持W3C标准的浏览器在添加事件时 用addEventListener(event,fn,useCapture)方法, 基中第3个参数useCapture是一个Boolean值, 用来设置事件是在事件捕获时执行, 还是事件冒泡时执行。
而不兼容W3C的浏览器(IE)用attachEvent()方法, 此方法没有相关设置, 不过IE的事件模型默认是在事件冒泡时执行的, 也就是在useCapture等于false的时候执行, 所以把在处理事件时把useCapture 设置为false是比较安全, 也实现兼容浏览器的效果。
如下图所示:
案例分析:
下面通过一个简单的案例阐述冒泡原理:
定义一个html, 里面有三个简单的dom 元素:div1,div2, span,div2包含span,div1 包含div2;而它们都在body 下:
<body id="body">
<div id="box1" class="box1">
<div id="box2" class="box2">
<span id="span">This is a span.</span>
</div>
</div>
</body>
在这个基础上,我们实现下面的功能:
a.body添加 click 事件监听,当body捕获到event事件时,打印出事件发生的时间和 触发事件的节点信息:
<script type="text/javascript">
window.onload = function() {
document.getElementById("body").addEventListener("click",eventHandler);
}
function eventHandler(event) {
console.log("时间:"+new Date(event.timeStamp)+" 产生事件的节点:" + event.target.id +" 当前节点:"+event.currentTarget.id);
}
</script>
当我们依次点击 span box2 box1 body后 ,控制台会输出一下信息:
无论我们点击那个元素,都会产生click事件,并且body都会捕获到。然后调用函数事件。这就像水泡一样,从底网上冒,直到最上面。
遇到这种情况,我们经常有一个常用方法,就是阻止冒泡
阻止冒泡事件
在点击span的时候,不想他再往上冒泡,怎么办?对于某个节点而言,如果我们不想它现在处理的事件继续往上冒泡的话,我们可以终止冒泡,在对应的处理函数内,加入event.stopPropagation(),终止事件的广播分发,这样事件停留在本节点,不会再往外传播了,得出:
<script type="text/javascript">
window.onload = function() {
document.getElementById("span").addEventListener("click",function(event){
console.log('我是最里层 span ');
event.stopPropagation();
});
document.getElementById("box2").addEventListener("click",function(event){
console.log('我是box2层 ');
event.stopPropagation();
});
}
</script>
经过这样一段代码,点击最里层元素,不会再冒泡,执行到最外层的事件了。