「这是我参与11月更文挑战的第24天,活动详情查看:2021最后一次更文挑战」
冒泡
让我们先来看一个简单的示例:
以下代码中,我们在div上加了一个onclick事件,但是如果我们点击div里面的p标签,会发现,这个事件也被执行了,这是为什么呢?
其实这就是所谓的事件冒泡,冒泡(bubbling)原理很简单:
当一个事件发生在一个元素上,它会首先运行在该元素上的处理程序,然后运行其父元素上的处理程序,然后一直向上到其他祖先上的处理程序。
可以想象把一颗石头投入水中,泡泡会一直从水底冒出水面。也就是说,事件会从最内层的元素开始发生,一直向上传播,直到document对象。
💥 注意:这里传递的仅仅是事件,并不传递所绑定的事件函数。所以如果父级没有绑定事件函数,就算传递了事件,也不会有什么表现,但事件确实传递了。
假如现在又一个3层的嵌套FORM > DIV > P,它们各自拥有一个处理程序:
<form onclick="alert('form')">FORM
<div onclick="alert('div')">DIV
<p onclick="alert('p')">P</p>
</div>
</form>
点击内部的 <p> 会首先运行 onclick:
- 在该
<p>上的。 - 然后是外部
<div>上的。 - 然后是外部
<form>上的。 - 以此类推,直到最后的
document对象。
如果此时你
- 点击
p标签,将会弹出3个alert,顺序为p→div→form - 点击
div标签,将会弹出2个alert,顺序为div→form - 点击
form标签,只会弹出1个form
event.target
之前有说过,当事件发生时,浏览器会创建一个 event 对象,将详细信息放入其中,并将其作为参数传递给处理程序。其中的
event.target可以准确地获取事件源(指的是真正触发事件的那个元素)
event.currentTarget指绑定了事件监听的元素(触发事件元素的父级元素)
如开头的这个示例:
如果点击了p标签,则event.target获取到的是p标签,而event.currentTarget获取到的则是绑定了事件的div标签。
💥注意:如果直接打印
event,展开这个对象会发现currentTarget的值为null,但是如果是直接打印event.currentTarget,可以获取到具体的值。(currentTarget 在你控制台展开查看的时候,已经不存在了。你要是想拿到它,需要赋值给一个值,然后再进行操作。)
👉 Stack Overflow相关问题回答
👉 github上的相关问题回答
停止冒泡
取消事件冒泡有两种方式:
-
标准的W3C 方式:
e.stopPropagation(); 这里的stopPropagation是标准的事件对象的一个方法,调用即可 -
非标准的IE方式:
ev.cancelBubble=true; 这里的cancelBubble是 IE事件对象的属性,设为true即可
阻止冒泡的函数封装
function stopBubble(e) {
//如果提供了事件对象,则这是一个非IE浏览器
if ( e && e.stopPropagation ){
//因此它支持W3C的stopPropagation()方法
e.stopPropagation();
}else{
//否则,我们需要使用IE的方式来取消事件冒泡
window.event.cancelBubble = true;
}
}
如果一个元素在一个事件上有多个处理程序,即使其中一个停止冒泡,其他处理程序仍会执行。换句话说,event.stopPropagation() 停止向上移动,但是当前元素上的其他处理程序都会继续运行。
有一个 event.stopImmediatePropagation() 方法,可以用于停止冒泡,并阻止当前元素上的处理程序运行。使用该方法之后,其他处理程序就不会被执行。
参考资料:
🎨【点赞】【关注】不迷路,更多前端干货等你解锁
往期推荐