React渲染机制
一、react-dom 渲染
模块说明
- 作用:React的DOM和服务器渲染器的入口点。它可以与通用的React包配对,一般用于渲染web端
执行过程
- 执行react-dom的render方法。
// ReactDOM.render render( element: React$Element<any>, // react创建的基础对象 container: DOMContainer, // 根节点 callback: ?Function, // 执行完毕后的回调函数 ) { /* ...处理一些警告等 */ // 实际执行的方法 return legacyRenderSubtreeIntoContainer( null, element, container, false, // 是否为服务端渲染 callback, ); }
- 初始化ReactRoot节点作为react根节点容器
//--------legacyRenderSubtreeIntoContainer--------// // 为了方便阅读,只保留了关键代码 function legacyRenderSubtreeIntoContainer( parentComponent: ?React$Component<any, any>, children: ReactNodeList, container: DOMContainer, forceHydrate: boolean, // 默认为false callback: ?Function, ) { // 检查是否存在root,即ReactRoot let root: Root = (container._reactRootContainer: any); if (!root) { // 创建ReactRoot实例 // 清除div#root内容并返回 new ReactRoot() root = container._reactRootContainer = legacyCreateRootFromDOMContainer(container,forceHydrate); // 调用ReactRoot.prototype.render root.render(children, callback); } }
- 创建FiberRoot,作为fiber架构树根节点
function ReactRoot( container: DOMContainer, // 真实的dom节点 isConcurrent: boolean, // 是否是异步挂载(默认是false) hydrate: boolean, // 是否是服务端渲染(默认是false) ) { // 创建一个FiberRoot,挂在this上,也就是root节点上 // 作为渲染树的根节点,待调度过程使用 const root = createContainer(container, isConcurrent, hydrate); this._internalRoot = root; } ReactRoot.prototype.render = function() { /* ... */} ReactRoot.prototype.unmount = function() { /* ... */} ReactRoot.prototype.legacy_renderSubtreeIntoContainer = function() { /* ... */} ReactRoot.prototype.createBatch = function() { /* ... */}
- 调用
ReactRoot.prototype.render
方法//-------ReactRoot.prototype.render-------方法 // 获取FiberRoot const root = this._internalRoot; // 创建一个Work实例,类似于Promise const work = new ReactWork(); callback = callback === undefined ? null : callback; /* dev警告 */ if (callback !== null) { work.then(callback); } // 更新容器,不一定是实时更新 updateContainer(children, root, null, work._onCommit); return work;
- 创建调度任务,并同步执行该调度任务
- 创建FiberRoot,作为fiber架构树根节点
- 执行
performWorkOnRoot
方法,初始化一颗工作树,并提交该树渲染到页面上let finishedWork = root.finishedWork; if (finishedWork !== <