react作为现在三大前端框架之一,使用的人非常之多,相信你们对react api的使用已经是很熟悉了,但是可能我们不会去研究它底层的一些机制和原理,这个专栏主要做的事情就是带领我们一起揭开react底层原理这层面纱,持续更新中。。。
一、react的快速响应
在我们开始深入了解react之前,我们先来了解一下react的前身今世,我们可以从react哲学中看到这样一句话
这里react提到一个词,叫快速响应,但其实react这个框架它本身真的是快速响应吗?其实不是的,如果将react横向对比vue的话,react的快速响应可能不堪一击,因为vue通过模版的方式在编译时可以知道哪些是变量数据,在编译阶段实现了一些优化,而react采用的则是近乎原生js的方式,所以无法通过编译时进行优化,所以只能在运行时从头遍历才能知道哪些数据发生了变化,这就导致react在更新某一个数据的时候,需要从头到尾遍历的更新。
二、react的前身今世
在知道react如何快速响应之前,我们先来了解一下react的前身今世,react现在大概可以分为两个阶段,分别为v16之前(旧架构) 和v16之后(新架构)
1. v16之前
react在v16之前的架构主要可以分为两部分,分别是:
- Reconciler(协调器)—— 负责找出变化的组件
- Renderer(渲染器)—— 负责将变化的组件渲染到页面上
Reconciler主要负责找出变化的节点,Renderer负责将变化的节点渲染出来,这两个过程是一个递归且同步的过程,也就是说Reconciler在找出有变化的节点时,就会通知Renderer进行页面的更新,可以参照下图所示
存在的问题
如果这个时候我们发生变化的树是一颗层级很深的树,那么就需要花费比较长的一段时间,而且我们也知道js是一门单线程的脚本语言,一帧的时间内除了要运行js脚本之外,还需要运行浏览器相关的绘制工作,如果因为某些脚本代码停留在主线程的时间比较长,在一帧的时间内无法运行页面渲染的相关工作,那么就会出现卡顿的现象。
我们还可以想一想,是否所有的更新都必须响应呢?
一些更新的优先级
是的,react也注意到了这个问题,比如,此时存在两个更新,一个是网络请求类型的更新,一个是用户自身产生的更新(比如在搜索框输入了文字)。
此时存在两个更新,如果是v16之前,如果网络类型的更新先产生,那么就会先更新网络请求类型的更新,再响应用户输入的更新。
如果刚好这颗需要更新的树很大,那么用户输入的内容可能会得不到实时的响应,用户就可以明显的感觉卡顿,如下图
可以看到,输入的更新会等到上一次更新完再更新,但是像输入事件一般都是输入高反馈事件,用户通常希望输入就能即时反馈,优先级是比网络类型更新高的。
所以如果输入的更新可以打断网络类型的更新,那么用户的就能得到即时反馈,等到输入类型更新完再去更新网络类型的更新,而且像这种网络请求的事件,就算延迟了100、200毫秒,用户也是感知不太到的,但是如果输入一个字母等待100、200毫秒,那这个是可以感受到的。
具体流程如下
结论:
从上面可以看出,react旧架构存在的几个问题, 一是递归时长时间占用js线程,二是没有办法响应一些高优先级的更新,所以react更换新的架构主要解决的就是这两个问题。
解决方案分别是:
一、将更新按一定的时间切成几个小的更新也就是时间分片,留一些时间给浏览器响应渲染的工作
二、赋予更新任务优先级,不同的任务拥有不同的优先级,高优先级的任务可以打断低优先级的任务
2.v16之后
上面说的两个解决方案都有一个共同的前提,那就是都要支持可中断的更新,那么react旧架构是否支持可中断的更新呢?
通过上图可以看到,由于是递归的同步更新,所以如果在更新的途中发生了中断,那么最终页面上显示的内容就跟预想的结果不一样,所以基于这个原因,react决定重写整个架构。
新的架构
新的架构有三个部分,比之前的新增了一个调度器模块(从宏观的角度看待三个模块的关系)
- Scheduler(调度器)—— 调度任务的优先级,高优任务优先进入Reconciler
- Reconciler(协调器)—— 负责找出变化的组件
- Renderer(渲染器)—— 负责将变化的组件渲染到页面上
这里的调度器主要做的事情就是负责处理不同优先级的任务,高优先级的任务先提交给协调器进行处理,同时还处理时间分片相关的工作。
除了上面新增的调度器之外,react还新增了一种新的结构,那就是fiber,为什么有fiber?
在React15及以前,Reconciler采用递归的方式创建虚拟DOM,递归过程是不能中断的。如果组件树的层级很深,递归会占用线程很多时间,造成卡顿。
为了解决这个问题,React16将递归的无法中断的更新重构为异步的可中断更新,由于曾经用于递归的虚拟DOM数据结构已经无法满足需要。于是,全新的Fiber架构应运而生。
三、总结
上面我们主要介绍了react的新老架构之间的不同,以及旧架构存在的问题,还有这些问题的解决方案,在下一章节我们会先给大家介绍一下fiber数据结构的相关知识,敬请期待!