React 启动过程分析
经历一个月的学习整理,站在前人的肩膀上,对 React 有了一些浅薄的理解,希望记录自己的学习过程的同时也可以给大家带来一点小帮助。如果此系列文章对您有些帮助,还望在座各位义夫义母不吝点赞关注支持 🐶,也希望各位大佬拍砖探讨
React 包概览
-
「react」 react 基础包,只提供定义 react 组件(React Element)的必要函数,一般来说需要和渲染器(react-dom,react-native)一同使用.在编写 react 应用的代码时,大部分都是调此包的 api.
-
「react-dom」 react 渲染器之一,是 react 与 web 平台连接的桥梁(可以在浏览和 nodejs 环境中使用),将 react-reconciler 中的运行结果输出到 web 界面上.在编写 react 应用的代码时,大多数场景下,能用到此包的就是一个入口函数 ReactDOM.render(
<APP/>
,doucument.getElementByID('root)'),其余使用的 api,基本是 react 包提供的 -
「react- reconciler」 react 得以运行的核心包(综合协调 react-dom,react,scheduler 各包之前的调用与配合).管理 react 应用状态的输入和结果的输出.将输入信号最终转换成输出信号传递给渲染器
-
「scheduler」 调度机制的核心实现, 控制由 react-reconciler 送入的回调函数的执行时机, 在 concurrent 模式下可以实现任务分片. 在编写 react 应用的代码时, 同样几乎不会直接用到此包提供的 api. 核心任务就是执行回调(回调函数由 react-reconciler 提供) 通过控制回调函数的执行时机, 来达到任务分片的目的, 实现可中断渲染(concurrent 模式下才有此特性)
react 应用的启动过程
位于 react-dom 包,衔接 reconciler 运行流程中的输入步骤
启动模式
-
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 模式的小部分功能.
// BlockingRoot
// 1. 创建ReactDOMRoot对象
const reactDOMBlockingRoot = ReactDOM.createBlockingRoot(
document.getElementById('root'),
);
// 2. 调用render
reactDOMBlockingRoot.render(<App />); // 不支持回调
-
Concurrent 模式: ReactDOM.createRoot(rootNode).render(<App />)
. 实现了时间切片等功能
// ConcurrentRoot
// 1. 创建ReactDOMRoot对象
const reactDOMRoot = ReactDOM.createRoot(
document.getElementById('root')
);
// 2. 调用render
reactDOMRoot.render(<App />); // 不支持回调
启动流程
在调用入口函数之前,reactElement(
和 DOM 对象 div#root
之间没有关联