研究了React源码后知道的答案
宏观结构
以下代码源码均以 v18 版本来进行解说
参考图解 React-架构分层,可以把 react 整体结构分成以下两个核心层
react
暴露的接口层- 调度器
scheduler
---构造器react-reconciler
---渲染器react-dom
组成的内核层
以下问题,是按照内核层三层架构的主干链路中核心源码进行解答,如果问题欢迎提出。
调度器 scheduler
核心职责只有一个,就是执行回调
- 把 react-reconciler 提供的回调函数, 包装到一个任务对象中
- 在内部维护一个任务队列, 优先级高的排在最前面
- 循环消费任务队列, 直到队列清空
时间切片原理
时间切片(time slicing)的主要作用是执行时间分割,让出主线程(把控制权归还给浏览器,让浏览器可以处理用户输入、UI 绘制等紧急任务)
构造器 react-reconciler
主要功能分为以下四个阶段
- 输入: 暴露 api 函数(如: scheduleUpdateOnFiber), 供给其他包(如 react 包)调用
- 注册调度任务: 与调度中心(scheduler 包)交互, 注册调度任务 task, 等待任务回调
- 执行任务回调(render): 在内存中构造出 fiber 树, 同时与渲染器(react-dom)交互, 在内存中创建出与 fiber 对应的 DOM 节点.
- 输出(commit): 与渲染器(react-dom)交互, 渲染 DOM 节点
以上阶段的功能源码顺序是:
- 输入:只要涉及到需要改变 fiber 的操作(无论是首次渲染还是后续更新),最后都会间接调用scheduleUpdateOnFiber
- 注册调度任务:ensureRootIsScheduled
- 执行任务回调:performSyncWorkOnRoot或performConcurrentWorkOnRoot
- 输出:commitRoot
哪些方法可以触发更新
只要涉及到更新操作,都会间接调用 scheduleUpdateOnFiber 函数。主动发起更新主要有三种方式:
class
组件中调用setState
function
组件中调用hook
对象暴露处的dispatchAction
- 在
root
节点上重复调用 render,官方示例
如何注册调度任务
- performSyncWorkOnRoot 通过scheduleSyncCallback注册同步任务,逻辑是往全局的
syncQueue
队列中插入回调函数 callback,最后通过flushSyncCallbacks同步调用 - performConcurrentWorkOnRoot 通过
scheduler
封装的scheduleCallback来注册异步任务。
render 阶段的源码流程
performSyncWorkOnRoot 构建 fiber 树的源码流程如下
performConcurrentWorkOnRoot 构建 fiber 树的源码流程如下
- 需要时间切片进入renderRootConcurrent,不需要则进入 renderRootSync
- renderRootConcurrent 进入workLoopConcurrent,renderRootSync 进入 workLoopSync
- performUnitOfWork
- beginWork
- completeUnitOfWork
详细说下 render 阶段
render 阶段的构建过程分为以下两个阶段:
- 深度优先向下的 beginWork 探寻阶段:若节点有更新则计算新状态和 diff 之后生成新的 fiber 节点,然后在新的 fiber 节点打上 effectTag,最后 return 它的子节点,若子节点为空(也就是叶子节点)则进入 completeWork 回溯阶段
- completeWork 回溯阶段:根据 beginWork 阶段创建的 fiber 节点创建(或更新)其 DOM 对象,并且自下而上收集 effectList,最终收集到 root 上
在 Concurrent 模式下,render 阶段可被打断
可中断更新的实现原理
详细说下 commit 阶段
commit 阶段主要处理的是副作用队列,分为 以下三个阶段:
- commitBeforeMutationEffects:DOM 变更前,处理副作用队列中带有 Snapshot,Passive 标记的 fiber 节点
- commitMutationEffects:DOM 变更,界面得到更新. 处理副作用队列中带有 Placement, Update, Deletion, Hydrating 标记的 fiber 节点
- commitLayoutEffects:DOM 变更后,处理副作用队列中带有 Update | Callback 标记的 fiber 节点
渲染器 react-dom
- 引导 react 应用的启动(通过 ReactDOM.render)
- 实现 HostConfig 协议(源码在 ReactDOMHostConfig.js 中), 能够将 react-reconciler 包构造出来的 fiber 树表现出来, 生成 dom 节点(浏览器中), 生成字符串(ssr)