说到Fiber,不得不说说他的发展史:
React15 架构
-
React16
之前的版本比对更新虚拟DOM
的过程是采用循环递归方式
来实现的,这种比对方式有一个问题,就是一旦任务开始进行就无法中断
,如果应用中数组数量庞大,主线程被长期占用,直到整颗虚拟DOM树比对更新完成之后主线程才被释放
,主线程才能执行其他任务,这就会导致一些用户交互或动画等任务无法立即得到执行,页面就会产生卡顿,非常的影响用户体验。 -
主要原因就是
递归无法中断
,执行重的任务耗时较长,javascript又是单线程的
,无法同时执行其他任务,导致任务延迟页面卡顿用户体验差
。React15架构可以分为两层:
Reconciler
(协调器)—— 负责找出变化的组件Renderer
(渲染器)—— 负责将变化的组件渲染到页面每当有更新发生时,Reconciler会做如下工作:
- 调用
函数组件、或class组件的render方法,将返回的JSX转化为虚拟DOM
- 将
虚拟DOM和上次更新时的虚拟DOM对比
- 通过对比找出
本次更新中变化的虚拟DOM
- 通知
Renderer将变化的虚拟DOM渲染到页面上
而
React15
使用的是栈调和器,由于递归执行,所以更新一旦开始,中途就无法中断
,当调用层级很深时,递归更新时间超过了屏幕刷新时间间隔,用户交互就会卡顿。 - 调用
react 16架构
React16
架构可以分为三层:
-
Scheduler
(调度器)—— 调度任务的优先级,高优任务优先进入Reconciler
-
Reconciler
(协调器)—— 负责找出变化的组件 -
Renderer
(渲染器)—— 负责将变化的组件渲染到页面上相比React15,16增加了一个Scheduler(调度器)
并发&调度(Concurrency & Scheduler)
-
Concurrency
并发:有能力优先处理更高优事务,同时对正在执行的中途任务可暂存,待高优完成后,再去执行
。 -
Scheduler
协调调度: 在浏览器每一帧的时间中,预留一些时间给JS线程,React利用这部分时间更新组件,当预留的时间不够用时,React将线程控制权交还给浏览器使其有时间渲染UI,React则等待下一帧时间到来,继续被中断的工作
。
在源码中,预留的初始时间是5ms
考虑到可中断渲染,并可重回构造。React自行实现了一套体系叫做 React fiber 架构。
Scheduler 运行核心点
-
有个任务队列
queue
,该队列存放可中断的任务。 -
workLoop
对队列里取第一个任务currentTask
,进入循环开始执行。 -
当该任务没有时间 或 需要中断 (渲染任务 或 其他高优任务插入等),则让出主线程。
-
requestAnimationFrame
计算一帧的空余时间; -
使用
new MessageChannel ()
执行宏任务;Fiber架构
-
界面通过
vdom
描述,但是不是直接手写vdom
,而是jsx
编译产生的render function
之后以后生成的。这样就可以加上state、props 和一些动态逻辑,动态产生 vdom
。 -
vdom
生成之后不再是直接渲染,而是先转成fiber
,这个vdom 转 fiber 的过程叫做 reconcile
。 -
fiber
是一个链表结构
,可以打断,这样就可以通过 requestIdleCallback 来空闲调度 reconcile,这样不断的循环,直到处理完所有的 vdom 转 fiber 的 reconcile
,就开始commit
,也就是更新到dom
。 -
reconcile
的过程会提前创建好dom
,还会标记出增删改,那么commit
阶段就很快了。 -
从之前递归渲染时做
diff
来确定增删改以及创建dom
,提前到了可打断的reconcile
阶段,让commit
变得非常快,这就是fiber
架构的目的和意义。
Fiber的数据结构有三层信息: (采用链表结构)
-
-
实例属性
该Fiber
的基本信息,例如组件类型等。 -
构建属性
构建属性 (return、child、sibling
) -
工作属性
-
数据的变更会导致UI层的变更
-
为了减少对
DOM
的直接操作,通过Reconcile
进行diff查找,并将需要变更节点,打上标签,变更路径保留在effectList里
-
待变更内容要有
Scheduler
优先级处理涉及到diff
等查找操作,是需要有个高效手段来处理前后变化,即双缓存机制
。 -
链表结构即
可支持随时随时中断的诉求
schedule
就是通过空闲调度每个 fiber节点的reconcile(vdom转fiber)
,全部reconcile
完了就执行commit
。React Fiber 核心: 自行实现 虚拟栈帧
。总结
React16
使用的是全新的"Fiber
调和器",这就依托于React16
的重点了—Fiber架构。React16
能够实现中断调和
,分批次异步地调和
。从而达到不因为JS执行时间过久影响浏览器渲染
。
-
-