JS中的事件冒泡、事件捕获、事件委托
DOM事件流(event flow)存在三个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段。

Dom标准事件流的触发的先后顺序为:先捕获再冒泡。即当触发dom事件时,会先进行事件捕获,捕获到事件源之后通过事件传播进行事件冒泡。
addEventListener的第三个参数
在我们平常用的addEventListener方法中,一般只会用到两个参数,一个是需要绑定的事件,另一个是触发事件后要执行的函数,然而addEventListener还可以传入第三个参数:
ts
//useCapture bool
document.addEventListener('click',()=>{} ,useCapture)事件冒泡和事件捕获
试一试:
vue
<template>
<div w-300px h-300px bg-red id="red">
<div w="50%" h="50%" bg-green id="green">
<div w="50%" h="50%" bg-blue id="blue"></div>
</div>
</div>
</template>
<script setup lang="ts">
import { onMounted } from 'vue'
function click1(){
alert('red')
}
function click2(){
alert('green')
}
function click3(){
alert('blue')
}
onMounted(()=>{
/* 第三个参数默认值是false 为true的话是下到上 `red--green--blue` */
document.getElementById('red').addEventListener('click',click1,false)
document.getElementById('green').addEventListener('click',click2,false)
document.getElementById('blue').addEventListener('click',click3,false)
})
</script>事件委托
事件委托利用了事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。
例如:有十个div每个div都需要添加同一个的点击事件:随机生成颜色。这个时候就可以把点击事件绑定父组件上面,然后通过事件冒泡把事件传递给子组件,从而实现事件委托。
试一试:
1
2
3
4
5
6
7
8
9
10
vue
<template>
<div flex="~" @click="click4">
<div v-for="i in 10" w-50px h-50px bg-white border="~ solid" rounded text=" black" flex="~" items-center justify-center >{{i}}</div>
</div>
</template>
<script setup lang="ts">
function click4(event){
console.log(event.target)
event.target.style.backgroundColor = bgChange();
}
function random(number) {
return Math.floor(Math.random() * number);
}
function bgChange() {
const rndCol = `rgb(${random(255)}, ${random(255)}, ${random(255)})`;
return rndCol;
}
</script>优点:
- 减少内存消耗,提高性能。
- 简化了
dom节点更新时,相应事件的更新
缺点:
- 事件委托基于冒泡,对于不冒泡的事件不支持。
- 层级过多,冒泡过程中,可能会被某层阻止掉。
- 理论上委托会导致浏览器频繁调用处理函数,虽然很可能不需要处理。
指南