# React笔记
# React的理念
快速响应:
- 速度快
- 响应自然
速度快:
由于React语法的灵活性,在编译时无法区分可能变化的部分,所以它为了速度快需要在运行时做更多的努力,例如:
- 使用
PureComponent或React.memo构建组件 - 使用
shouldComponentUpdate生命周期钩子 - 渲染列表时使用
key - 使用
useCallback和useMemo缓存函数和变量
响应自然:
将同步更新变为可中断的异步更新,在浏览器每一帧的时间中,预留一些时间给JS线程,React利用这部分时间更新组件,源码中预留的时间是5ms。当预留的时间不够用时,React将线程控制权交还给浏览器使其有时间渲染UI,React则等待下一帧时间到来继续被中断的工作。
# React15架构及缺点
# 架构
Reconciler(协调器):负责找出变化的组件Renderer(渲染器):负责将变化的组件渲染到页面上
# 更新流程
当有发生更新时,Reconciler会做:
- 调用函数组件、或class组件的
render方法,将返回的JSX转化为虚拟DOM - 将虚拟DOM和上次更新时的虚拟DOM对比
- 通过对比找出本次更新中变化的虚拟DOM
- 通知Renderer将变化的虚拟DOM渲染到页面上
# React15架构的缺点:
在Reconciler中,更新的方式是递归更新子组件,而对于递归更新,更新一旦开始,中途就无法中断,所以当层级很深时,递归更新时间就可能会超过16.6ms(主流浏览器刷新频率为60Hz,即每1000ms/60Hz,16.6ms刷新一次),这样用户交互就会卡顿。
而解决以上问题的关键就是用可中断的异步更新代替同步的更新,但是React15的架构却是不支持异步更新的。
因为在React15,Reconciler和Renderer是交替着工作,当前一轮更新的任务结束之后,第二轮再进行Renconciler,由于整个过程都是同步的,所以如果此时中途中断更新,就会使得后面的任务不执行,渲染也就停止了。
# React16架构
# 架构:
Scheduler(调度器):调度任务的优先级,高优先级的任务先进入ReconcilerReconciler(协调器):负责找出变化的组件Renderer(渲染器):负责将变化的组件渲染到页面上
相比于React15,新增了Scheduler。
# Scheduler:
一个独立于React的库,实际上是一个功能完备的requestIdleCallbackpolyfill。
它产生的原因是:
- 浏览器需要用是否有剩余时间作为任务中断的标准,所以我们需要一种机制,当浏览器有剩余时间的时候通知我们。
- 部分浏览器已经实现了这个API,也就是
requestIdleCallback,不过由于它有以下缺点而被React放弃使用了:- 浏览器兼容性问题
- 触发频率不稳定,受很多因素影响。比如当我们的浏览器切换tab后,之前tab注册的
requestIdleCallback触发的频率会变得很低
所以React实现了一个功能更完备的requestIdleCallbackpolyfill:Scheduler。
作用:
- 在空闲时间触发回调,以通知我们浏览器是否有剩余时间做任务中断
- 提供了多种调度优先级供任务设置
# 更新流程
- Reconciler与Renderer不再是交替工作
- 当产生一个更新,先将更新内容交给Scheduler,Scheduler会判断有没有其它高优先级更新需要执行,若是没有的话则将更新的内容交给Reconcoler
- 当Scheduler将任务交给Reconciler后,Reconciler会为变化的虚拟DOM打上代表增/删/更新的标记
- 整个Scheduler与Reconciler的工作都在内存中进行。只有当所有组件都完成Reconciler的工作,才会统一交给Renderer
- Renderer接收到通知,将变化的虚拟DOM渲染到页面上
# Fiber架构
# 代数效应
代数效应是函数式编程中的一个概念,用于将副作用从函数调用中分离。
代数效应在React中的应用:
useStateuseRefuseReducer
代数效应与Generator:
异步可中断更新可以理解为:更新在执行过程中可能会被打断(浏览器时间分片用尽或有更高优任务插队),当可以继续执行时恢复之前执行的中间状态。
代数效应中try...handle的作用就是为了满足以上需求。
而此功能与浏览器原生的Generator很像,但它存在一些缺陷,因此不被使用:
- 类似
async,Generator也是传染性的,使用了Generator则上下文的其他函数也需要作出改变。这样心智负担比较重。 Generator执行的中间状态是上下文关联的。如果后面的计算需要依赖与前面的计算结果,就需要重新计算。
代数效应与Fiber:
Fiber:中文翻译为纤程,与进程(Process)、线程(Thread)、协程(Coroutine)同为程序执行过程。
可以理解为纤程是协程的一种实现,而在JS中协程的实现就是Generator。
所以,我们可以将纤程(Fiber)、协程(Generator)理解为代数效应思想在JS中的体现。
React Fiber可以理解为:
React内部实现的一套状态更新机制。支持任务不同优先级,可中断与恢复,并且恢复后可以复用之前的中间状态。
其中每个任务更新单元为React Element对应的Fib
