React技术揭秘2-3 render阶段流程概览

4,215 阅读2分钟

本文节选自 React技术揭秘

在本章剩下部分我们会讲解Fiber节点是如何被创建并构建Fiber树的。

render阶段开始于workLoopConcurrent方法的调用。

function workLoopConcurrent() {
  while (workInProgress !== null && !shouldYield()) {
    performUnitOfWork(workInProgress);
  }
}

其中workInProgress代表当前已创建的workInProgress fiber

performUnitOfWork方法会创建下一个Fiber节点并赋值给workInProgress,并将workInProgress与已创建的Fiber节点连接起来构成Fiber树

如果当前浏览器帧没有剩余时间,shouldYield会中止循环,直到浏览器有空闲时间后再继续遍历。

你可以从这里看到workLoopConcurrent的源码

我们知道Fiber Reconciler是从Stack Reconciler重构而来,通过遍历的方式实现可中断的递归,所以performUnitOfWork的工作可以分为两部分:“递”和“归”。

“递”阶段

首先从rootFiber开始向下深度优先遍历。为遍历到的每个Fiber节点调用beginWork方法

该方法会根据传入的Fiber节点创建子Fiber节点,并将这两个Fiber节点连接起来。

当遍历到叶子节点(即没有子组件的组件)时就会进入“归”阶段。

“归”阶段

在“归”阶段会调用completeWork处理Fiber节点

当某个Fiber节点执行完completeWork,如果其存在兄弟Fiber节点(即fiber.sibling !== null),会进入其兄弟Fiber的“递”阶段。

如果不存在兄弟Fiber,会进入父级Fiber的“归”阶段。

“递”和“归”阶段会交错执行直到“归”到rootFiber。至此,render阶段的工作就结束了。

例子

以上一节的例子举例:

function App() {
  return (
    <div>
      i am
      <span>KaSong</span>
    </div>
  )
}

ReactDOM.render(<App/>, document.getElementById('root'));

对应的Fiber树结构:

fiber
fiber

render阶段会依次执行:

1. rootFiber beginWork
2. App Fiber beginWork
3. div Fiber beginWork
4. "i am" Fiber beginWork
5. "i am" Fiber completeWork
6. span Fiber beginWork
7. span Fiber completeWork
8. div Fiber completeWork
9. App Fiber completeWork
10. rootFiber completeWork

注意 之所以没有 “KaSong” Fiber 的 beginWork/completeWork,是因为作为一种性能优化手段,针对只有单一文本子节点的FiberReact会特殊处理。

这里提供一个 在线Demo,你可以自己调试一下。

我在beginWorkcompleteWork调用时打印fiber.tagfiber.type

你可以从ReactWorkTags.js看到Fiber节点的所有tag定义。

相信多调试几次,你一定能明白方法的调用顺序

Demo地址

总结

本节我们介绍了render阶段会调用的方法。在接下来两节中,我们会讲解beginWorkcompleteWork做的具体工作。

参考资料

The how and why on React’s usage of linked list in Fiber to walk the component’s tree