react在创建root的时候会将所有的事件都挂在root dom上面
有些事件没有捕获(比如abort),所以只注册了冒泡的方法
大多数事件既有捕获也有冒泡,所以注册了两次
demo
export default function Index(){
const refObj = useRef(null)
useEffect(()=>{
const handler1 = ()=>{
console.log('dom注册的冒泡')
}
const handler2 = ()=>{
console.log('dom注册的捕获')
}
refObj.current.addEventListener('click',handler1)
refObj.current.addEventListener('click',handler2, true)
return () => {
refObj.current.removeEventListener('click',handler1)
refObj.current.removeEventListener('click',handler2, true)
}
},[])
const handleClick = ()=>{
console.log('child 冒泡阶段执行')
}
const handleCaptureClick = ()=>{
console.log('child 捕获阶段执行')
}
const handleClick1 = ()=>{
console.log('parent 冒泡阶段执行')
}
const handleCaptureClick1 = ()=>{
console.log('parent 捕获阶段执行')
}
return <div onClick={handleClick1} onClickCapture={handleCaptureClick1}>
<button ref={refObj} onClick={handleClick} onClickCapture={handleCaptureClick} >点击</button>
</div>
}
react将事件任务的优先级设置为2(不同事件优先级不同,click是2)
当点击button的时候,调度到click事件的时候,会进入到root dom的捕获,react通过原始事件得知触发该事件的targetDom,通过之前保存在dom上的props拿到dom的捕获事件,并把它放入事件队列里面
然后通过fiber return得到父级div,再收集它的捕获事件
此时事件队列有两个任务[button, div]
因为是捕获,所以要倒着遍历执行
输出
接着再触发button dom的捕获事件和冒泡事件,不通过react绑定在dom上的事件是没有调度的,直接执行
最后事件冒泡到root dom上,再经历一次从targetDom的事件收集,再执行事件队列,最后输出