冒泡和捕获
2022年10月14日大约 1 分钟
事件处理阶段
event.eventPhase
可以获取事件的阶段数(capturing=1,target=2,bubbling=3)
- 捕获阶段:通过祖先链(从 Window 开始)向下到达元素
- 目标阶段:事件到达目标元素
- 冒泡阶段:事件从元素上开始冒泡,在途中调用处理程序
冒泡(bubbling)
当一个事件发生在一个元素上,会首先运行在该元素上的处理程序,然后运行其父元素上的处理程序,然后一直向上到其他祖先上的处理程序
- 几乎所有的事件都会冒泡
focus
不会冒泡
event.target
引发事件的那个嵌套层级最深的元素(事件实际发生的位置)被称为目标元素,可以通过
event.target
访问
- 是引发事件的目标元素,在冒泡过程中不会发生变化
this
(同event.currentTarget
),表示当前元素
停止冒泡
冒泡事件从目标元素开始向上冒泡。通常,它会一直上升到
<html>
,然后再到document
对象,有些事件甚至会到达window
,它们会调用路径上所有的处理程序
event.stopPropagation()
用于停止冒泡,如果一个元素在一个事件上有多个处理程序,即使其中一个停止冒泡,其他处理程序仍会执行
event.stopImmediatePropagation()
用于停止冒泡,并阻止当前元素上的处理程序运行
捕获(capturing)
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<style>
div,
span,
i {
display: inline-block;
padding: 24px;
border: 1px solid #000;
}
</style>
</head>
<body>
<div id="div">
<span id="span">
<i id="i">冒泡测试</i>
</span>
</div>
<script>
for (let elem of document.querySelectorAll('*')) {
elem.addEventListener('click', () => {
console.log(`Capture:${elem.tagName} - ${event.eventPhase}`)
}, {
capture: true
})
elem.addEventListener('click', () => {
console.log(`Bubbling:${elem.tagName} - ${event.eventPhase}`)
})
}
</script>
</body>
</html>