启动过程
React 应用启动的 3 种模式
在当前稳定版react@17.0.2源码中, 有 3 种启动方式. 先引出官网上对于这 3 种模式的介绍, 其基本说明如下:
-
legacy模式:ReactDOM.render(<App />, rootNode). 这是当前 React app 使用的 方式. 这个模式可能不支持这些新功能(concurrent 支持的所有功能).// LegacyRoot
ReactDOM.render(<App />, document.getElementById('root'), (dom) => {}); // 支持callback回调, 参数是一个dom对象 -
Blocking 模式:
ReactDOM.createBlockingRoot(rootNode).render(<App />). 目前正在实验中, 它仅提供了concurrent模式的小部分功能, 作为迁移到concurrent模式的第一个步骤.// BlockingRoot
// 1. 创建ReactDOMRoot对象
const reactDOMBlockingRoot = ReactDOM.createBlockingRoot(
document.getElementById('root'),
);
// 2. 调用render
reactDOMBlockingRoot.render(<App />); // 不支持回调 -
Concurrent 模式:
ReactDOM.createRoot(rootNode).render(<App />). 目前在实验中, 未来稳定之后,打算作为 React 的默认开发模式. 这个模式开启了所有的新功能.// ConcurrentRoot
// 1. 创建ReactDOMRoot对象
const reactDOMRoot = ReactDOM.createRoot(document.getElementById('root'));
// 2. 调用render
reactDOMRoot.render(<App />); // 不支持回调
创建全局对象
无论Legacy, Concurrent或Blocking模式, react 在初始化时, 都会创建 3 个全局对象
- 属于
react-dom包, 该对象暴露有render,unmount方法, 通过调用该实例的render方法, 可以引导 react 应用的启动.
-
- 属于
react-reconciler包, 作为react-reconciler在运行过程中的全局上下文, 保存 fiber 构建过程中所依赖的全局状态. - 其大部分实例变量用来存储
fiber 构造循环(详见两大工作循环)过程的各种状态.react 应用内部, 可以根据这些实例变量的值, 控制执行逻辑.
- 属于
-
- 属于
react-reconciler包, 这是 react 应用中的第一个 Fiber 对象, 是 Fiber 树的根节点, 节点的类型是HostRoot.
- 属于
这 3 个对象是 react 体系得以运行的基本保障, 一经创建大多数场景不会再销毁(除非卸载整个应用root.unmount()).
在创建HostRootFiber时, 其中fiber.mode属性, 会与 3 种RootTag(ConcurrentRoot,BlockingRoot,LegacyRoot)关联起来.
export function createHostRootFiber(tag: RootTag): Fiber {
let mode;
if (tag === ConcurrentRoot) {
mode = ConcurrentMode | BlockingMode | StrictMode;
} else if (tag === BlockingRoot) {
mode = BlockingMode | StrictMode;
} else {
mode = NoMode;
}
return createFiber(HostRoot, null, null, mode); // 注意这里设置的mode属性是由RootTag决定的
}
注意:fiber树中所有节点的mode都会和HostRootFiber.mode一致(新建的 fiber 节点, 其 mode 来源于父节点),所以HostRootFiber.mode非常重要, 它决定了以后整个 fiber 树构建过程.