第一步
首先我们先写一个在按钮上触发合成事件和原生事件的代码。
javascript
import React, {useEffect, useRef} from 'react'
import { createRoot} from 'react-dom/client'
const App = () => {
const buttonRef = useRef(null);
useEffect(()=>{
buttonRef.current.addEventListener('click',()=>{
console.log('原始冒泡');
})
buttonRef.current.addEventListener('click',()=>{
console.log('原始捕获');
}, true)
return ()=>{
buttonRef.current.removeEventListener('click');
}
},[])
const onClick = () => {
console.log('react冒泡');
}
# const onClickCapture = () => {
console.log('react捕获');
}
return(
<button onClick={onClick} onClickCapture={onClickCapture} ref={buttonRef} >开始</button>
)
}
const root = document.getElementById('app')
createRoot(root).render(<App></App>)
上面的代码在 button 元素上面绑定了react onClick 和 onClickCapture 两个合成事件,以及通过 addEventListener绑定了两个原生事件。 如果此时我们点击 button 按钮,四个打印的顺序会是什么样子的呢? 要回答上面的问题,我们要知道什么是捕获事件和冒泡事件,然后我们还需要研究下 react 的合成事件机制。
浏览器捕获事件和冒泡事件
上面的流程图为我们展示了 button 触发点击事件时,整个事件的流程,首先从 window 开始捕获,最后捕获到 button 上面,这是一个完整的捕获流程,接着开始冒泡流程,首先从 button 开始冒泡,最后冒泡到 window 上面最后结束。
react 合成事件
可以看到,react 其实帮我们把所有的事件都在捕获和冒泡阶段去代理,这样我们在代码中写的 onClick 和 onClickCapture 两个事件其实并没有去真正的走一遍监听流程,而是在事件触发后,由 react 代理事件去处理,最后找到对应元素上面真正要执行的事件处理函数。
所以上面代码的打印顺序是
react 捕获, 原始捕获,原始冒泡,react 冒泡