ReactDOM 源码之: 📚DOM`Root 和 Fiber Root

903 阅读3分钟

React 元素和组件是从 Root 开始渲染的。那么我们 React Root 是如任何创建的呢?

两种 Root 根构造函数

  • ReactDOMRoot 用与创建并发模式的构造函数
  • ReactDOMBlockingRoot 用与创建 blocking、legacy 模式的根

三种创建方法

三种创建方式代表了 React 三种 DOM 渲染方法,

  • createRoot
    • 实例化 ReactDOMRoot 类
  • createBlockingRoot
    • 实例化 ReactDOMBlockingRoot 类
  • createLegacyRoot
    • 实例化 ReactDOMBlockingRoot 类

其次 ReactDOMRoot 和 ReactDOMBlockingRoot 上面的挂载了相同的原型方法:

  • render 用于渲染元素
  • unmount 用于卸载元素

他们都是用于更新 updateContainer 更新容器, 更新容器的阶段不在 ReactDOM 中而是在接入 React 的协调阶段, 协调阶段与 Fiber 有直接关系

ReactDOMRoot 与 ReactDOMBlockingRoot 的区别

他们的内部都是调用 createRootImpl 使用给 _internalRoot 赋值。仅仅是传入的参数有差异

// ReactDOMRoot 是 ConcurrentRoot 模式,传入 ConcurrentRoot 根
this._internalRoot = createRootImpl(container, ConcurrentRoot, options);

// ReactDOMBlockingRoot
this._internalRoot = createRootImpl(container, tag, options);

createRootImpl 创建 Root 实现

// 实现创建 Root 的时候
const root = createContainer(container, tag, hydrate, hydrationCallbacks);

return root;

createContainer、updateContainer

创建容器和更新容器,不发生在 ReactDOM 中,而是发生在 React Reconiler 阶段。

特殊的传统模式渲染

传统的渲染的模式,直接调用 ReactDOM 的 render 方法。到了这里我们并不是直接就开始创建 React 的根。render 方法是直接调用了 legacyRenderSubtreeIntoContainer 方法,此方式事件将 react 元素渲染到指定的 dom 容器当中,它会有如下的操作:

  1. 读取 container._reactRootContainer,没有就调用 legacyCreateRootFromDOMContainer 函数创建一个 container._reactRootContainer,然后走第一次渲染的流程,更新容器
  2. 如果读取到 container._reactRootContainer 是有内容的,不在需要创建,直接更新。
  3. 回到 legacyCreateRootFromDOMContainer 函数中,我们的确定我们的问题是在哪里创建了我们传统的根。
  4. 进入 legacyCreateRootFromDOMContainer 函数, 直接调用 createLegacyRoot。到这里就我们之前分析的三种模式中的传统模式结合起来了。

小结

  1. 在进入协调之前,我们需要确定用哪种模式渲染。当然一般是老传统模式。
  2. 传统的模式比较特殊,它是 ReactDOMrender 方法渲染出来的。需要额外的初始化 root。然后走第一次渲染流程。
  3. 使用 createRootImpl 实现了 createContainer,进入了协调阶段

协调开始

在 React 协调开始吗createContainer 函数是在调用 createFiberRoot。要创建一个 Fiber 根。(注意 Fiber 根,与 Fiber 存在引用关系,但是他们不是同一个东西)。

其实就是实例化(具有:current属性)了一个 FiberRootNode 构造函数。然后处理 createHostRootFiber 实例(真的Fiber 根, 具有: stateNode 属性)的引用关系返回(其实这里还有很大的关系)。current 属性和 stateNode 属性相互应用。这个 fiber 数据结构中有巨大的作用。

到这开我们的根 root 就创阿金完毕了。然后就可以拿这个 root 去更新容器了。

总结

React 采用的链表的数据结构,根节点是我们渲染 React 的地方。React 创建根有三种模式。React 创建了根的内容,其实本质就是进入了协调阶段,生成 FiberRoot 和 host fiber。他们之间通过 current 属性和 stateNode 相互引用。