当前位置: 首页 > 科技观察

自己创建一个ReactDOM

时间:2023-03-20 23:54:33 科技观察

大家好,我是Kason。React可以看做是三部分的组合:scheduler,scheduler,用于调度任务reconciler,coordinator,用于计算任务引起的副作用renderer,renderer,用于在宿主环境中执行副作用,这三个是独立的封装,我们项目中引入的ReactDOM可以看做是将以下三部分代码进行了封装:scheduler的主要逻辑,reconciler部分的逻辑,ReactDOMrenderer的主要逻辑,本文将教大家如何实现基于官方协调器的迷你ReactDOM。本文参考HelloWorldCustomReactRenderer[1]项目初始化通过CRA构建项目(或使用现有项目):create-react-appxxx新建customRenderer.js,引入react-reconciler并完成初始化://本文使用的reconciler版本为0.26.2importReactReconcilerfrom'react-reconciler';consthostConfig={};constReactReconcilerInst=ReactReconciler(hostConfig);其中hostConfig为宿主环境的配置项。最后,customRenderer.js导出一个包含render方法的对象:,false);}returnReactReconcilerInst.updateContainer(reactElement,domElement._rootContainer,null,callback);}};在项目入口文件中,将ReactDOM替换为我们实现的CustomRenderer:importReactDOMfrom'react-dom';importCustomRendererfrom'./customRenderer';//替换ReactDOMCustomRenderer.render(,document.getElementById('root'));实现ReactDOM接下来我们实现hostConfig配置,先填空函数,避免应用报错:shouldSetTextContent(){}、createInstance(){}、createTextInstance(){}、appendInitialChild(){}、finalizeInitialChildren(){}、clearContainer(){}、appendInitialChild(){}、appendChild(){}、appendChildToContainer(){},prepareUpdate(){},commitUpdate(){},commitTextUpdate(){},removeChild(){}}注意这里唯一的布尔类型配置项supportsMutation,即宿主环境的API支持mutation,也就是DOMAPI的工作方式,如element.appendChild和element.removeChild。如果是Native环境,这不是工作方式。接下来我们实现这些API。实现API这些API可以分为以下几类。初始化环境信息getRootHostContext和getChildHostContext用于初始化上下文信息。生成DOM节点createInstance用于创建DOM节点createTextInstance用于创建文本节点CreateTextInstance可以实现如下:createTextInstance:(text)=>{returndocument.createTextNode(text);}关键逻辑判断shouldSetTextContent用于判断是否组件的children是Text节点,实现如下:shouldSetTextContent:(_,props)=>{returntypeofprops.children==='string'||typeofprops.children==='number';},DOM操作appendInitialChild为用于插入DOM节点,实现如下:appendInitialChild:(parent,child)=>{parent.appendChild(child);},commitTextUpdate用于改变文本节点,实现如下:commitTextUpdate(textInstance,oldText,newText){textInstance.text=newText;},removeChild用于删除一个子节点,实现如下:正常呈现:对于完整的demo地址见:完整的Demo地址[2]小结学习了这篇文章,我们实现了一个简单的ReactDOM。如果你想在任何可以绘制UI的环境中使用React,你可以使用react-reconciler在这个环境中实现React。例如,IntroductionToReactNativeRenderers[3]教你如何在Native环境中实现React。参考资料[1]HelloWorldCustomReactRenderer:https://agent-hunt.medium.com/hello-world-custom-react-renderer-9a95b7cd04bc[2]完整Demo地址:https://codesandbox.io/s/quiet-feather-05gvk?file=/src/index.js[3]ReactNative渲染器简介:https://agent-hunt.medium.com/introduction-to-react-native-renderers-aka-react-native-is-the-java-and-react-native-renderers-are-828a0022f433