在讲捕获和冒泡之前我们先看一个例子
<div class="grandpa">
<div class="papa">
<div class="child">
<button class="button">
文字
</button>
</div>
</div>
</div>
给每个层级加上事件监听,如果点击了文字,就打出数字
grandpa.addEventListener('click', () => {
console.log(1)
})
papa.addEventListener('click', () => {
console.log(2)
})
child.addEventListener('click', () => {
console.log(3)
})
button.addEventListener('click', () => {
console.log(4)
})
打印出了1,2,3,4.就是说我们点击了文字,不仅仅是打印出了数字4,它的上级也都做出了响应。
也就是说我们点击了文字,相当于点击了"child""papa""grandpa",但这里就有问题,点击了文字,先调用的那个函数,有两个方案:
- fn(grandpa)=>fn(papa)=>fn(child)=>fn(button)
- fn(button)=>fn(child)=>fn(papa)=>fn(grandpa)
事实上两中路径都可以,而路径1就是捕获,路径2就是冒泡
捕获(Capture page)
浏览器检查元素的最外层祖先,是否在捕获阶段中注册了一个onclick事件处理程序,如果是,则运行它。 然后,它移动到中单击元素的下一个祖先元素,并执行相同的操作,然后是单击元素再下一个祖先元素,依此类推,直到到达实际点击的元素。
冒泡(Bubbling page)
浏览器检查实际点击的元素是否在冒泡阶段中注册了一个onclick事件处理程序,如果是,则运行它 然后它移动到下一个直接的祖先元素,并做同样的事情,然后是下一个,等等,直到它到达元素。
区分事件冒泡和捕获
xxx.addEventListener('click',fn,bool)
-
如果bool不传或者传的为falsy值,就是走冒泡,当游览器在冒泡阶段发现有事件监听,就调用函数,并提供事件信息。
-
如果bool为true,就是走捕获,当游览器在捕获阶段发现有事件监听,就调用函数,并提供事件信息。
取消事件冒泡
x.stopPropagation()
可以取消冒泡,一般用于封装某些独立的组件。