事件冒泡
它是什么?
什么是事件冒泡,事件沿着DOM树向这个对象的父级传播。(通俗记忆:气体(泡泡)在水底往水面上冒,就是冒泡)事件冒泡指事件往父级元素方向冒,这就是事件冒泡,需要注意的是冒泡的只是事件,并不事件绑定的处理函数。不管是父级以上元素是否绑定了事件,冒泡都是存在的。只有人为手动的添加代码去阻止,否则会一直冒泡到window对象,(IE8-到document对象)。
事件冒泡是一直存在的,没有认为阻止的话,必须为同一种事件才存在冒泡传递。
以下常见几种不冒泡的事件:blur 表单失去焦点;,focus 表单获取焦点;load 加载 ;unload;
看实例:
//html结构
<div id="father" style="background: forestgreen">
<div id="son" style="background: gold">
<div id="now" style="background: hotpink"></div>
</div>
</div>
//各自事件
now.onclick = function () {
alert('now');
}
son.onclick = function () {
alert('son');
}
father.onclick = function () {
alert('father');
}
当点击 now时,触发 now 的click事件,然而son,father的click事件也会被触发。这种现象就是事件冒泡。
它有什么用?
利用事件冒泡可以实现事件委托。那么什么又是事件委托呢。用我自己的说,就是孙子的事,委托祖宗来做。对于属于数据渲染构建的节点,使用 this 面向对象的方法来绑定事件较为麻烦,需要在节点被创建后才能绑定事件,而使用事件委托的方式,只需要在他的父级元素及以上绑定事件都可以。然后配合**事件源对象(被点击的那个对象)(事件源对象见另外一篇文章)event.target
**即完成完成原本想要绑定的事件和处理函数。
好处是什么?
- 事件冒泡的存在为事件委托提供了实现的基础。
- 利用target事件源对象,在传播的过程中不会改变
缺点又是什么?
有些时候事件冒泡就给我们带来不必要的麻烦,比如上述案例,我只想点击 now 时出现弹窗,但是冒泡的存在 ,son、father 都出现了弹窗,这并不是我们想要的结果。这就是事件冒泡的不好之处。
如何阻止事件冒泡
阻止事件冒泡是存在兼容性的。标准的写法是:event.stopPropagation();
IE8-写法是:event.cancelBubble = true;
,在需要阻止的对象里面加入阻止代码,即可。
now.onclick = function () {
alert('now');
}
son.onclick = function () {
alert('son');
ev.stopPropagation();//阻止冒泡
}
father.onkeydown = function () {
alert('father');
}
此时点击now时,son也会出现弹窗,但是 father 并不会出现弹窗 ,因为冒泡到son时就被阻止了。
不确定当前浏览器版本,可采用兼容性阻止事件冒泡处理
//阻止冒泡兼容
if (ev.stopPropagation) {
ev.stopPropagation();//阻止冒泡
} else {
ev.cancelBubble = true;
}