大家好,我卡颂。
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.2
import 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';
// 替换 ReactDOM
CustomRenderer.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
。
欢送退出人类高质量前端框架群,带飞