React源码01 - 开篇
本源码学习笔记始发:React 源码学习-yuque
1. React16 架构
React 是一个 UI 框架:UI = Fn(X)。
React16架构可以分为三层:
- Scheduler(调度器)—— 调度任务的优先级,高优任务优先进入 Reconciler
- Reconciler(协调器)—— 负责找出变化的组件
- Renderer(渲染器)—— 负责将变化的组件渲染到页面上
主流的浏览器刷新频率为60Hz,即每(1000ms / 60Hz)16.6ms浏览器刷新一次。我们知道,JS可以操作DOM,GUI渲染线程
与 JS线程
是互斥的。所以JS脚本执行和浏览器布局、绘制不能同时执行。
在每16.6ms时间内,需要完成如下工作:
JS脚本执行 ----- 样式布局 ----- 样式绘制
既然我们以浏览器是否有剩余时间作为任务中断的标准,那么我们需要一种机制,当浏览器有剩余时间时通知我们。
其实部分浏览器已经实现了这个API,这就是 requestIdleCallback。但是由于以下因素,React 放弃使用:
- 浏览器兼容性
- 触发频率不稳定,受很多因素影响。比如当我们的浏览器切换tab后,之前tab注册的 requestIdleCallback 触发的频率会变得很低。
React 实现了功能更完备的 requestIdleCallback polyfill,这就是 Scheduler,除了在空闲时触发回调的功能外,Scheduler 还提供了多种调度优先级供任务设置。
当 Scheduler 将任务交给 Reconciler 后,Reconciler 会为变化的虚拟 DOM 打上代表增/删/更新的标记,类似这样:
export const Placement = /* */ 0b0000000000010;
export const Update = /* */ 0b0000000000100;
export const PlacementAndUpdate = /* */ 0b0000000000110;
export const Deletion = /* */ 0b0000000001000;
整个 Scheduler 与 Reconciler 的工作都在内存中进行。只有当所有组件都完成 Reconciler 的工作后,才会统一交给 Renderer。
Renderer 根据 Reconciler 为虚拟 DOM 打的标记,同步执行对应的 DOM 操作。
image.png其中红框中的步骤随时可能由于以下原因被中断:
- 有其他更高优任务需要先更新
- 当前帧没有剩余时间
由于红框中的工作都在内存中进行,不会更新页面上的DOM,即使反复中断用户也不会看见更新不完全的DOM。
因此可以说 Scheduler 和 Reconciler 是和平台无关的,而和平台相关的是 Renderer。
2. 源码位置
packages 包中:
主要是 react、react-dom、react-reconciler、scheduler,react-dom 和 react native 都重度依赖 react-reconciler。
react 包不大,主要是一些入口定义,而大部分的代码都在跟平台相关的 react-dom 和 react-reconciler 中。