React 的架构
第一章 React理念 - 新的React架构 - 《React 技术揭秘》 - 书栈网 · BookStack React16架构 React16架构可以分为三层: Scheduler(调度器)—— 调度任务的优先级,高优任务优先进入Reconciler Reconciler(协调器)—— 负责找出变化的组件 Renderer(渲染器)—— 负责将变化的组件渲染到页面上 可以看到,相较于React15,React16中新增了Scheduler(调度器),让我们来了解下他。 Scheduler(调度器) 既然我们以浏览器是否有剩余时间作为任务中断的标准,那么我们需要一种机制,当浏览器有剩余时间时通知我们。 其实部分浏览器已经实现了这个API,这就是requestIdleCallback (opens new window)。但是由于以下因素,React放弃使用: 浏览器兼容性 触发频率不稳定,受很多因素影响。比如当我们的浏览器切换tab后,之前tab注册的requestIdleCallback触发的频率会变得很低 基于以上原因,React实现了功能更完备的requestIdleCallbackpolyfill,这就是Scheduler。除了在空闲时触发回调的功能外,Scheduler还提供了多种调度优先级供任务设置。 Scheduler (opens new window)是独立于React的库 为什么调度器使用 MessageChannel React的Scheduler使用MessageChannel来产生宏任务,而不用setTimeout是因为setTimeout有最小延迟的问题,嵌套调用时会有4ms的限制。 Scheduler需要将主线程让给浏览器进行渲染,所以必须使用宏任务,因为微任务会在同一事件循环中执行,无法让出主线程。MessageChannel产生的宏任务正好满足这个需求。 MessageChannel的兼容性更好。同时,MessageChannel的执行时机比requestAnimationFrame更可靠,后者在浏览器窗口隐藏时会暂停,影响调度。 Reconciler(协调器) 我们知道,在React15中Reconciler是递归处理虚拟DOM的。让我们看看React16的Reconciler (opens new window)。 我们可以看见,更新工作从递归变成了可以中断的循环过程。每次循环都会调用shouldYield判断当前是否有剩余时间。 /** @noinline /function workLoopConcurrent() { // Perform work until Scheduler asks us to yield while (workInProgress !== null && !shouldYield()) { workInProgress = performUnitOfWork(workInProgress); }} 那么React16是如何解决中断更新时DOM渲染不完全的问题呢? 在React16中,Reconciler与Renderer不再是交替工作。当Scheduler将任务交给Reconciler后,Reconciler会为变化的虚拟DOM打上代表增/删/更新的标记,类似这样: export const Placement = / / 0b0000000000010;export const Update = / / 0b0000000000100;export const PlacementAndUpdate = / / 0b0000000000110;export const Deletion = / */ 0b0000000001000; 全部的标记见这里 (opens new window) 整个Scheduler与Reconciler的工作都在内存中进行。只有当所有组件都完成Reconciler的工作,才会统一交给Renderer。 你可以在这里 (opens new window)看到React官方对React16新Reconciler的解释 Renderer(渲染器) Renderer根据Reconciler为虚拟DOM打的标记,同步执行对应的DOM操作。 在React16架构中整个更新流程为: 其中红框中的步骤随时可能由于以下原因被中断: 有其他更高优任务需要先更新 当前帧没有剩余时间 由于红框中的工作都在内存中进行,不会更新页面上的DOM,所以即使反复中断,用户也不会看见更新不完全的DOM(即上一节演示的情况)。 实际上,由于Scheduler和Reconciler都是平台无关的,所以React为他们单独发了一个包react-Reconciler (opens new window)。你可以用这个包自己实现一个ReactDOM,具体见参考资料 总结 通过本节我们知道了React16采用新的Reconciler。 Reconciler内部采用了Fiber的架构。 Fiber是什么?他和Reconciler或者说和React之间是什么关系?我们会在接下来三节解答。



