最近在学习React 源码深度解析 高级前端工程师必备技能》https://s.imooc.com/SUq8J2i
源码部分其中一节讲了ReactDom.render()
创建更新。
整理如下 MarkDown使用不是很熟练将就看
第一部分 创建ReactRoot
-
ReactDom.render()
ReactDom.render()
接受3个参数,element
、container、callback
返回下方代码的执行结果。
legacyRenderSubtreeIntoContainer( null, element,
container,false,callback)
-
legacyRenderSubtreeIntoContainer
legacyRenderSubtreeIntoContainer
接收5个参数:(
parentComponent
、children
、container、forceHydrate
、callback
)在这个方法中 定义
root = container
.reactRootContainer
=
legacyCreateRootFromDOMContainer(container,forceHydrate,)
通过 new React()*创建ReactRoot对象的方法下面有说明 *
后执行
root.render (children, callback)
也就是
container
.reactRootContainer
.render(children, callback);最后返回
return DOMRenderer.getPublicRootInstance(
root._internalRoot)
返回实例由上文legacyCreateRootFromDOMContainer(container, forceHydrate,)方法创建添加的属性
_internalRoot
。 -
legacyCreateRootFromDOMContainer创建返回ReactRoot
function legacyCreateRootFromDOMContainer( container: DOMContainer, forceHydrate: boolean, // 是否复用已有子节点 ): Root { /* 不重要 忽略 const shouldHydrate = forceHydrate || shouldHydrateDueToLegacyHeuristic(container) // First clear any existing content. if (!shouldHydrate) { let warned = false let rootSibling while ((rootSibling = container.lastChild)) { container.removeChild(rootSibling) } } */ // Legacy roots are not async by default. const isConcurrent = false return new ReactRoot(container, isConcurrent, shouldHydrate) // 创建ReactRoot } function ReactRoot( container: Container, isConcurrent: boolean, hydrate: boolean, ) { // 这个root 不是上面的 root const root = DOMRenderer.createContainer(container, isConcurrent, hydrate) this._internalRoot = root }
也就是说
ReactRoot._internalRoot
// 内部本质root
其实等于DOMRenderer.createContainer(container, isConcurrent, hydrate)
结合
上面的2. legacyRenderSubtreeIntoContainer
root
= container.reactRootContainer
=legacyCreateRootFromDOMContainer(container, forceHydrate)
= => new ReactRoot
省略中间步骤 root <=> new ReactRoot()
结合function ReactRoot
root._internalRoot 也其实就是 DOMRenderer.createContainer(container, isConcurrent, hydrate)返回,一个 FiberRoot。
也就是说 上面2. legacyRenderSubtreeIntoContainer 实际上创建了一个 ReactRoot 并返回其公共根实例(getPublicRootInstance)
return DOMRenderer.getPublicRootInstance(
root._internalRoot)
返回实例
整理
- root = container.reactRootContainer ≈ new ReactRoot() // ReactRoot
1.1root._internalRoot
=DOMRenderer.createContainer(container, isConcurrent, hydrate))
1.1.1 DOMRenderer.createContainer=>创建FiberRoot - 也就是说 root.internalRoot 为 一个FiberRoot实例。 root的本质是FiberRoot。internal中文为 (本质、内部)
- DOMRenderer.getPublicRootInstance(
root._internalRoot
) // 接收一个FiberRoot返回其公共根实例 - 整个过程是建立
4.1root
为一个ReactRoot;
4.2root._inernalRoot
为一个FiberRoot,
4.3 ReactRoot还有render
方法也是第二部分的开始;
第二部分
-
ReactRoot.render()主要执行 DOMRenderer.updateContainer(children, root, null, work._onCommit)
其中root实际上为第一部分的ReactRoot._ineralRoot也就是FiberRoot,
而work._onCommit实际上为最开始传入的callback -
updateContainer()
function updateContainer( element: ReactNodeList, container: OpaqueRoot, parentComponent: ?React$Component<any, any>, callback: ?Function, ): ExpirationTime { const current = container.current const currentTime = requestCurrentTime() // 计算更新超时时间 const expirationTime = computeExpirationForFiber(currentTime, current) // 用超时时间来更新。 return updateContainerAtExpirationTime( element, container, parentComponent, expirationTime, callback, ) }
updateContainerAtExpirationTime
调用了scheduleRootUpdate
function updateContainerAtExpirationTime( element: ReactNodeList, container: OpaqueRoot, parentComponent: ?React$Component<any, any>, expirationTime: ExpirationTime, callback: ?Function, ) { // TODO: If this is a nested container, this won't be the root. const current = container.current const context = getContextForSubtree(parentComponent) if (container.context === null) { container.context = context } else { container.pendingContext = context } return scheduleRootUpdate(current, element, expirationTime, callback) }
-
scheduleRootUpdate
3.1生成一个update
3.2添加到更新队列enqueueUpdate(current, update)
3.3开始任务调度。 // 后续内容
3.4返回expirationTime
感谢能坚持看到这里 给点建议吧。