react学习系列——事件

77 阅读1分钟

react在创建root的时候会将所有的事件都挂在root dom上面

截屏2024-03-18 14.12.27.png

有些事件没有捕获(比如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的捕获事件,并把它放入事件队列里面

1122768494.png

然后通过fiber return得到父级div,再收集它的捕获事件

3820178870.png

此时事件队列有两个任务[button, div]

因为是捕获,所以要倒着遍历执行

输出

截屏2024-03-19 10.20.46.png

接着再触发button dom的捕获事件和冒泡事件,不通过react绑定在dom上的事件是没有调度的,直接执行

截屏2024-03-19 10.21.50.png

最后事件冒泡到root dom上,再经历一次从targetDom的事件收集,再执行事件队列,最后输出

截屏2024-03-19 10.23.20.png