React 中是如何处理事件的,现在下面简单的一段代码:
export default function App() {const AList = lazy(()=>import('./List.js'))const r = useRef(null) const [show, setShow] = useState(false);return (<><button onFocus={()=>{setShow(!show)}} >加载组件</button>{show ? <Suspense fallback="loading"><AList items={[{id:1, text:"123"}]}>asdf</AList></Suspense>:""}</>);
}
代码为 Button 绑定了 onFocus 事件,这里用 onFocus 是为了方便 debug。如果做一个框架要接管所有的事件处理,我们想一下应该如何处理,可以通过代理的方式,把所有可以监听到的事件交给代理去处理,最后在交给框架组件上绑定的对应事件进行处理。由于 JS 是冒泡事件模型,所有事件都会向上传递,只要监听最顶层容器就可以监听到所有事件,当点击发生的时候调用目标组件绑定的事件。
我们看一下,React 中怎么处理的。
组件注册事件
创建 Element,添加 props,这个 props 中就是 Focus 方法,将最终方法于 Element 绑定并包存在 Fiber 上。
绑定代码
Root 代理所有事件
创建 Root 时会监听所有事件:
方法中 loop 所有 Html 原生事件
事件触发
Focus 事件触发时,会执行 dispatchDiscreteEvent 方法,这个方法在 Root 代理监听时进行的绑定。
获取组件事件处理方法,这个方法在组件创建时进行的绑定。
总结
React 事件机制是一个代理模式,所有处理都由根组件监听并进行分发处理。