曾经的React15使用递归的方式去生成新的视图,现在的React16使用时间片结合双缓存树的机制去生成新的视图,从而使得视图更新不卡顿。
React15
- Reconciler(协调器)—— 负责找出变化的组件
- Renderer(渲染器)—— 负责将变化的组件渲染到页面上
Reconciler(协调器)
在React中可以通过this.setState、this.forceUpdate、ReactDOM.render等API触发更新。
每当有更新发生时,Reconciler会做如下工作:
- 调用函数组件、或class组件的
render方法,将返回的JSX转化为虚拟DOM - 将虚拟DOM和上次更新时的虚拟DOM对比
- 通过对比找出本次更新中变化的虚拟DOM
- 通知Renderer将变化的虚拟DOM渲染到页面上
Renderer(渲染器)
由于递归执行更新,所以更新一旦开始,中途就无法中断,直到完成视图更新。当层级很深时,递归更新时间超过了16ms,用户交互就会卡顿。
为了解决卡顿问题,引入了调度器的概念,并重写了React
React16
为了解决react的更新视图卡顿问题,于是出现了双缓存树。所谓的双缓存树要做的事情就是可以中断的去复制fiber节点,并且形成一颗新的fiber树。用新的fiber树去创建视图。
- Scheduler(调度器)—— 在时间片内,调度任务的优先级,高优任务优先进入Reconciler
- Reconciler(协调器)—— 负责找出变化的组件
- Renderer(渲染器)—— 负责将变化的组件渲染到页面上
在时间片内,调度器Scheduler会不断将更新任务给到Reconciler,Reconciler会往虚拟DOM中打上标记。如果时间片结束。等待下一个时间片调度器继续调度更新任务给到协调器,直到更新任务结束。这个过程就是scheduler和reconciler配合着去生成workInProgram树。
整个Scheduler与Reconciler的工作都在内存中进行。只有当所有组件都完成Reconciler的工作,才会统一交给Renderer。这个时候会把workInProgram树指针指向current Fiber
Renderer(渲染器)
Renderer根据Reconciler为虚拟DOM打的标记,同步执行对应的DOM操作。这个过程不会中断,会直接执行到全部结束。