整体流程概览
src/index.js --> ReactDOM.render --> 初始化应用并创建整个应用的根节点fiberRootNode,而每次调用render都会创建新的当前fiber树的根节点rootFiber --> performSyncWorkOnRoot(开始进入render阶段) --> commitRoot(进入commit阶段) render阶段开始于performSyncWorkOnRoot或performConcurrentWorkOnRoot方法的调用。这取决于本次更新是同步更新还是异步更新。
// performSyncWorkOnRoot会调用该方法
function workLoopSync() {
while (workInProgress !== null) {
performUnitOfWork(workInProgress);
}
}
// performConcurrentWorkOnRoot会调用该方法
function workLoopConcurrent() {
while (workInProgress !== null && !shouldYield()) {
performUnitOfWork(workInProgress);
}
}
每次render阶段都会遍历整颗fiber树,循环调用performUnitOfWork直到workInProgress为null,首屏渲染时会调用createWorkInProgress生成第一个workInProgress,后续在completeUnitOfWork中会赋值workInProgress = completedWork生成下一个workInProgress;更新时会判断是否命中优化来选择不同逻辑。
render阶段概览
- 递阶段:从rootFiber开始向下深度优先遍历。为遍历到的每个fiber节点调用beginWork,该方法作用是根据传入的fiber节点创建子fiber,并连接这两个fiber,当没有子组件时就进入归阶段;
- 归阶段:调用completeWork处理fiber,当某个fiber执行完completeWork时,如果其存在兄弟fiber(fiber.sibling !== null),则进入兄弟节点执行beginWork,否则会进入父级fiber的completeWork,一直归到rootFiber则render阶段完成。
- 例子:
function App() {
return (
<div>
i am
<span>weison</span>
</div>
)
}
以上在render阶段会一次执行:
- rootFiber beginWork
- 首次进入的是当前fiber树的根节点rootFiber,对应tag为3,首屏渲染时也只有这个的current !== null
2. App Fiber beginWork
3. div Fiber beginWork
4. "i am" Fiber beginWork
5. "i am" Fiber completeWork
6. span Fiber beginWork
- (单一文本子节点的fiber,react做了优化处理,不会进入weison的beginWork)
- span Fiber completeWork
- div Fiber completeWork
- App Fiber completeWork
- rootFiber completeWork