编程语言
首页 > 编程语言> > 自顶而下学习react源码 (1) 理念篇

自顶而下学习react源码 (1) 理念篇

作者:互联网

理念篇

​ 解决这个问题的关键就是:在浏览器每一帧的时间中,预留一些时间给JS线程,React利用这部分时间更新组件

​ 解决CPU瓶颈的关键是实现时间切片,而时间切片的关键是:将同步的更新变为可中断的异步更新。

老的react架构

分为两层:Reconciler(协调器)—— 负责找出变化的组件. Renderer(渲染器)—— 负责将变化的组件渲染到页面上

当有更新变化的时候,Reconclier会调用函数组件或者类组件的render方法,得到虚拟dom,然后进行diff算法比对,将变化的虚拟dom叫个Renderer渲染到页面上。

该架构的缺点:在Reconciler中,mount组件调用mountComponent方法,而update组件调用updateComponent方法,两个方法都会递归更新子组件,一旦开始,无法中断,当层级很深的时候,就会超过16ms,导致卡顿。react15的架构支持中断异步更新吗?

答案是否定的:老的架构,Reconciler和Renderer阶段是交替工作的,当有一处变化的时候,Reconciler比对完变化就立马给到Renderer去渲染,然后再继续寻找变化,如果中途断掉的话,这样就会导致用户可能会看到渲染不完全的ui。

新的react架构

react16的架构分为三层:

scheduler

react16新增了一个调度器scheduler,因为需要以浏览器是否有剩余时间作为任务中断的标准,需要一种机制,当浏览器有剩余时间的时候通知我们。比如部分浏览器实现的requeistIdleCallback,但是因为浏览器兼容性和触发频率的不稳定性,react实现了功能更加完备的requestIdleCallbackpolyfill,就是S cheduler,除了能在浏览器空闲时出发回调,还可以提供多种任务调度的功能。

Reconciler

react15中·,Reconciler是递归处理虚拟do m的,而react16的Reconciler,从递归变成了可以中断的循环过程,每次循环都会调用shouldYeild判断当前是否有剩余时间,再决定是否继续处理j s。

/** @noinline */
function workLoopConcurrent() {
  // Perform work until Scheduler asks us to yield
  while (workInProgress !== null && !shouldYield()) {
    workInProgress = performUnitOfWork(workInProgress);
  }
}

并且为了解决中断更新渲染不完全的问题,Reconciler和Renderer不再交替工作,而是当Schedule将任务交给Reconciler后,Reconciler处理所有fiber,将变化的fiber打上effectTag标记,只有所有的组件都完成了Reconciler工作,才会统一交给Renderer。

Schedule和Reconciler的工作是在内存中完成的,是可以中断(当前帧没有剩余时间,或者有其他更高优先级任务需要更新)的,用户并没有体验,而Renderer阶段是不可以中断的,如果中断会导致页面渲染不完整。

简而言之,15的Reconciler和Renderer是交替进行的,中断会导致不完全的ui,而react16在所有的组件完成Reconciler阶段,才统一交给R enderer阶段去渲染,所以这中间,Reconciler是可以因为某些原因中断的。

FIber

虚拟Dom无法满足可中断的异步更新需求。Fiber应运而生,作为架构,Recocniler基于Fiber节点实现,称为Fiber Reconciler,而作为静态的数据结构,fiber对应每一个React element,保存了组件的类型,对应的dom信息,相当于对应每一个虚拟dom。作为动态的工作单元,每个fiber节点保存了本次更新中组件的状态。

学习文章地址:https://react.iamkasong.com/

标签:渲染,中断,自顶,更新,react,源码,Renderer,组件,Reconciler
来源: https://blog.csdn.net/lin_fightin/article/details/122775433