React源码系列1---React15和16的差别
React不同版本源码的差异
React的理念
速度快,响应自然
React的架构
React15
- Reconciler——找出发生变化的组件
- Renderer——渲染发生变化的组件
Reconciler
React中会通过this.setState,this.forceUpdate,ReactDom.render等方法更新组件
- 调用函数组件、class组件的
render方法,将返回的JSX转换为虚拟DOM- 将虚拟DOM与上次的进行比较
- 找出本次发生更新的虚拟DOM
- 通知Renderer将变化的虚拟DOM渲染到页面上
Renderer
每次更新发生的时候,Renderer接收到Reconciler的通知,将变化的组件渲染到当前的宿主环境
React15的缺陷
无法支持同步更新
递归的去更新会导致某写情况下页面的渲染结果不一致
在
Reconciler中,update的组件会调用updateComponent,mount的组件会调用mountComponent,这两个方法都是递归执行的JS是一门单线程的语言,他的
GUI渲染线程和JS主线程是互斥的,也就是说在页面执行我们的js代码的时候是不能够去渲染和绘制页面的,在我们渲染每一帧页面的时候:
JS代码执行-------样式布局-------样式绘制
- 当JS代码执行的时间超过每一帧的时长的时候,页面上就无法反映出本次渲染的结果
- 同时,对于
React来说,因为递归执行的原因,所以会导致页面一旦开始更新就无法终止;如果我们页面的层级变得很深,就会导致递归更新的时间过长,页面无法渲染- Scheduler和Reconciler是交替渲染的
React16
React16的架构有三层:
- Schduler(调度器)——调度人物的优先级,高优先级任务优先进入Reconciler
- Reconciler(协调器)——找出变化的组件(
Fiber架构?)- Renderer(渲染器)——将变化的组件渲染到页面上
其中Scheduler和Reconciler是平台无关的
Scheduler(调度器)
我们以浏览器每一帧是否有剩余时间作为任务中断的标准,需要有一种机制通知我们浏览器什么时候有剩余时间----
requestIdleCallback
React实现了requestIdleCallback的polyfill---Scheduler;除了在浏览器空闲时间触发回调,还提供了多种调度优先级
Reconciler(协调器)
在
React15中,Reconciler是递归处理虚拟DOM的
React16中更新的过程从递归变成了可以终中断的循环过程,每一次循环都回去调用shouleYield判断当前是否有剩余时间
function workLoopConcurrent() {
while(workInProgress !== null && !shouldYield()) {
workInProgress = performUnitOfWork(workInProgress)
}
}
关于
React15中的因为一些特殊原因导致中断更新的时候DOM渲染不完全的问题在
React16中,Reconciler和Renderer不是交替工作的。当Scheduler将任务交给Reconciler的时候,Reconciler会为变化的虚拟DOM搭上增/删/更新的标记其他的标记
因为整个Scheduler和Reconciler的过程都是在内存中进行的。只有当组件都完成在Reconciler的工作,才会统一交给Renderer
Renderer(渲染器)
Renderer根据Reconciler为虚拟DOM的打上的标记,同步执行对应的DOM操作。
Scheduler和Reconciler中的步骤随时会因为,有更高优先级的任务进来,或者当前帧没有剩余时间而中断。因为 Scheduler和Reconciler中的工作都是在内存中进行的,并不会更新页面,所以即使这个里面出现反复中断,也不会影响用户的体验(看见部分DOM更新不完全)