function workLoopSync() {
// Already timed out, so perform work without checking if we need to yield.
while (workInProgress !== null) {
workInProgress = performUnitOfWork(workInProgress);
}
}
let instance = createInstance(
type,
newProps,
rootContainerInstance,
currentHostContext,
workInProgress,
);
// ...
// This needs to be set before we mount Flare event listeners
workInProgress.stateNode = instance;
目前React Concurrent Mode还没有就绪,本文只分析同步模式下的渲染过程。
例子
初始化
首先初始化一些关键数据结构。
FiberRootNode
HostRoot
Fiber tree的根节点是一个tag为
HostRoot
的特殊Fiber。Update
首次渲染会在
updateContainer
方法中为HostRoot
安排一个Update
:该
Update
会加入到HostRoot
节点的UpdateQueue
中,其中payload
包含了这次要渲染的内容。主循环
在
prepareFreshStack
方法中,首先调用createWorkInProgress
方法,从HostRoot
节点创建出一个workInProgress
节点,赋值给全局变量workInProgress
:进入主循环
workLoop
:主循环就一个while循环,处理当前
workInProgress
,返回下一个workInProgress
。performUnitOfWork
beginWork
beginWork
返回workInProgress.child
作为下一个节点。首次渲染,
beginWork
走的是updateHostRoot
分支:updateHostRoot
方法首先会处理前面安排的Update任务,拿到最终的memoizedState
,其中包含了当前workInProgress
节点的nextChildren
。在本例子中,
nextChildren
是h1
元素:然后调用
reconcileChildFibers
方法构建子节点。最后返回h1节点作为下一个
workInProgress
节点:回到主循环,再次进入
beginWork
,h1是一个HostComponent
,走updateHostComponent
分支:h1的子元素是纯文本,无需再构建Fiber节点:
没有next节点了,进入
completeUnitOfWork
。completeUnitOfWork
伪代码如下:
从以上代码可以看出,这是一个深度优先遍历过程。
beginWork
沿着child
遍历,每轮迭代,都以workInProgress.child
节点作为下一个workInProgress
节点,直至到达叶子节点,React就会完成该节点(completeUnitOfWork),创建stateNode、标记Effects等。 叶子节点的工作完成后,检查sibling
,如果有sibling
节点,则返回sibling
节点作为下一个workInProgress
节点。如果没有
sibling
节点,则以return
节点作为下一个workInProgress
节点。completeWork
创建stateNode:
Effects List
从当前
workInProgress
节点开始,沿着return
链构建Effects List,通过firstEffect、lastEffect、nextEffect等指针串联成一个Effects链表,直至workInProgress
为空。提交
所有工作都完成以后,将workInProgress树挂载到
FiberRootNode
上:commitRoot:
遍历effects list:
在
commitMutationEffects
中,根据effectTag做不同的更新,本例首次渲染走的是commitPlacement
。在
commitPlacement
中插入dom节点,首先渲染过程完成!小结
这个例子比较简单,分析起来相对简单一些,实际渲染过程中会有更多细节。