React16架构可以分为三层:
- Scheduler(调度器)—— 调度任务的优先级,高优任务优先进入Reconciler
- Reconciler(协调器)—— 负责找出变化的组件
- Renderer(渲染器)—— 负责将变化的组件渲染到页面上
可以看到,相较于React15,React16中新增了Scheduler(调度器),让我们来了解下他。
既然我们以浏览器是否有剩余时间作为任务中断的标准,那么我们需要一种机制,当浏览器有剩余时间时通知我们。
其实部分浏览器已经实现了这个API,这就是requestIdleCallback (opens new window)。但是由于以下因素,放弃使用:
- 浏览器兼容性
基于以上原因,React
实现了功能更完备的requestIdleCallback
polyfill,这就是Scheduler。除了在空闲时触发回调的功能外,Scheduler还提供了多种调度优先级供任务设置。
我们知道,在React15中Reconciler是递归处理虚拟DOM的。让我们看看React16的Reconciler (opens new window)。
我们可以看见,更新工作从递归变成了可以中断的循环过程。每次循环都会调用shouldYield
判断当前是否有剩余时间。
那么React16是如何解决中断更新时DOM渲染不完全的问题呢?
export const Placement = /* */ 0b0000000000010;
export const PlacementAndUpdate = /* */ 0b0000000000110;
export const Deletion = /* */ 0b0000000001000;
整个Scheduler与Reconciler的工作都在内存中进行。只有当所有组件都完成Reconciler的工作,才会统一交给Renderer。
Renderer根据Reconciler为虚拟DOM打的标记,同步执行对应的DOM操作。
所以,对于我们在上一节使用过的Demo
乘法小Demo
关注公众号,后台回复222获得在线Demo地址
state.count = 1
,每次点击按钮state.count++
列表中3个元素的值分别为1,2,3乘以state.count
的结果
其中红框中的步骤随时可能由于以下原因被中断:
- 当前帧没有剩余时间
由于红框中的工作都在内存中进行,不会更新页面上的DOM,所以即使反复中断,用户也不会看见更新不完全的DOM(即上一节演示的情况)。
通过本节我们知道了React16
采用新的Reconciler
。
Reconciler
内部采用了Fiber
的架构。
Fiber
是什么?他和或者说和React
之间是什么关系?我们会在接下来三节解答。
同步/Debounce/Throttle/并发 情况下性能对比Demo