大家好,我卡颂。
React
能够看作是三局部的组合:
scheduler
,调度器,用于调度工作reconciler
,协调器,用于计算工作造成的副作用renderer
,渲染器,用于在宿主环境执行副作用
这三者都是独立的包,咱们我的项目里引入的ReactDOM
能够看作是以下三局部代码打包而成:
scheduler
的次要逻辑reconciler
局部逻辑ReactDOM renderer
的次要逻辑
本文会教你如何基于官网的reconciler
,实现迷你ReactDOM
。
本文参考Hello World Custom React Renderer
我的项目初始化
通过CRA
建设我的项目(或用已有我的项目):
create-react-app xxx
新建customRenderer.js
,引入react-reconciler
并实现初始化:
// 本文应用的reconciler版本是0.26.2import ReactReconciler from 'react-reconciler';const hostConfig = {};const ReactReconcilerInst = ReactReconciler(hostConfig);
其中hostConfig
就是宿主环境的配置项。
最初,customRenderer.js
导出一个蕴含render
办法的对象:
export default { render: (reactElement, domElement, callback) => { // 创立根节点 if (!domElement._rootContainer) { domElement._rootContainer = ReactReconcilerInst.createContainer(domElement, false); } return ReactReconcilerInst.updateContainer(reactElement, domElement._rootContainer, null, callback); }};
在我的项目入口文件,将ReactDOM
换成咱们实现的CustomRenderer
:
import ReactDOM from 'react-dom';import CustomRenderer from './customRenderer';// 替换ReactDOMCustomRenderer.render( <App />, document.getElementById('root'));
实现ReactDOM
接下来咱们实现hostConfig
配置,首先填充空函数防止利用报错:
const hostConfig = { supportsMutation: true, getRootHostContext() {}, getChildHostContext() {}, prepareForCommit() {}, resetAfterCommit() {}, shouldSetTextContent() {}, createInstance() {}, createTextInstance() {}, appendInitialChild() {}, finalizeInitialChildren() {}, clearContainer() {}, appendInitialChild() {}, appendChild() {}, appendChildToContainer() {}, prepareUpdate() {}, commitUpdate() {}, commitTextUpdate() {}, removeChild() {}}
留神这里惟一一个Boolean
类型的配置项supportsMutation
,他示意宿主环境的API
反对mutation
。
这是DOM API
的工作形式,比方element.appendChild
、element.removeChild
。如果是Native
环境则不是这种工作形式。
接下来咱们来实现这些API
。
实现API
这些API
能够分为如下几类。
初始化环境信息
getRootHostContext
与getChildHostContext
用于初始化上下文信息。
生成DOM节点
createInstance
用于创立DOM节点createTextInstance
用于创立文本节点
能够将createTextInstance
实现如下:
createTextInstance: (text) => { return document.createTextNode(text);}
要害逻辑的判断
shouldSetTextContent
用于判断组件的children
是否是文本节点
,实现如下:
shouldSetTextContent: (_, props) => { return typeof props.children === 'string' || typeof props.children === 'number';},
DOM操作
appendInitialChild
用于插入DOM
节点,实现如下:
appendInitialChild: (parent, child) => { parent.appendChild(child);},
commitTextUpdate
用于扭转文本节点
,实现如下:
commitTextUpdate(textInstance, oldText, newText) { textInstance.text = newText;},
removeChild
用于删除子节点,实现如下:
removeChild(parentInstance, child) { parentInstance.removeChild(child);}
当实现了所有API
后,页面就能失常渲染了:
残缺实现的Demo
地址见:残缺Demo地址
总结
通过本文的学习,咱们实现了一个繁难ReactDOM
。
如果你想在任何能够绘制UI
的环境应用React
,都能够利用react-reconciler
实现该环境下的React
。
比方,Introduction To React Native Renderers教你如何在Native
环境实现React
。
欢送退出人类高质量前端框架群,带飞