本文主要是介绍认识react16的fiber架构,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
认识react16的fiber架构
前言
React的Virtual DOM(VDOM),其核心的协调算法,即reconciliation,通过对比前后的Virtual DOM得出最小更新部分,再去渲染真实DOM,减少了频繁操作DOM的成本,使其深受大家关注。但随着前端工程化的发展,在大型的项目上reconciliation越来越不得满足,因此,React团队对reconciliation做出了优化,即Fiber架构。
React 渲染页面分为两个阶段:
- 调度阶段(reconciliation):在这个阶段 React 会更新数据生成新的 Virtual DOM,然后通过 Diff 算法,快速找出需要更新的元素,放到更新队列中去,得到新的更新队列。
- 渲染阶段(commit):这个阶段 React 会遍历更新队列,将其所有的变更一次性更新到 DOM 上。
react16之前
reconciler(被称为 stack reconciler ),以tree为单位,调度阶段(reconciliation)和渲染阶段(commit)按顺序执行,相当于没分阶段,形成同步渲染,采用自顶向下递归,从根组件或 setState() 后的组件开始,更新整个子树。如果组件层级深,组件树很大,就会一直占用浏览器主线程,导致布局、动画以及交互事件无法响应。
假如我们更新一个 state,有 1000 个组件需要更新,每个组件更新需要 1ms,那么我们就会有将近 1s 的时间,主线程被 React 占着用来调度,这段时间内用户的操作不会得到任何的反馈,只有当 React 中需要同步更新的任务完成后,主线程才被释放。对于这 1s 内 React 的调度,我们是无能为力的。
整个调度过程就如下图所示,组件树一旦过大,就会出现浏览器失去响应的情况,用户体验非常差。
react16之后
reconciler(被称为 fiber reconciler )为了解决主线程阻塞问题,使用了Fiber架构,以fiber(fiber tree)为单位,Fiber可以在调度阶段(reconciliation)对fiber tree做调度处理,行成异步渲染,但渲染阶段(commit)不能调度不能暂停。
Fiber
Fiber的出现使大量的同步计算可以被拆解、异步化,使浏览器主线程得以调控。从而使我们得到了以下权限:
- 暂停运行任务。
- 恢复并继续执行任务。
- 给不同的任务分配不同的优先级。
把一个耗时长的任务分成很多小片,每一个小片的运行时间很短,虽然总时间依然很长,但是在每个小片执行完之后,都给其他任务一个执行的机会,这样唯一的线程就不会被独占,其他任务依然有运行的机会。
Fiber 把更新过程碎片化,即把state更新任务拆分成多个时间小片,形成一个 Fiber 任务队列,执行过程如下面的图所示。
每执行完一段更新过程,就把控制权交还给 React 负责任务协调的模块,看看有没有其他紧急任务要做,如果没有就继续去更新,如果有优先级更高的任务,那就去做优先级高的任务。
调度阶段(reconciliation):Fiber调度
Fiber 在调度的时候会执行如下流程:
- 将一个state更新任务拆分成多个时间小片,形成一个 Fiber 任务队列.
- 在任务队列中选出优先级高的 Fiber 执行,如果执行时间超过了deathLine,则设置为pending状态挂起状态(即执行一段时间,会跳出找Fiber任务队列中更高级的任务,如果有就放弃当前任务,即使当前任务执行了一半,可能已经经历了一些生命周期,都会被打断从来)。
此过程,React 在 workinProgress Tree (并不是真实的virtualDomTree)上复用 current 上的 Fiber 数据结构来异步地(通过requestIdleCallback)来构建新的 tree,标记处需要更新的节点,放入队列中。 - 一个 Fiber 执行结束或挂起,会调用基于requestIdleCallback/requestAnimationFrame实现的调度器,返回一个新的 Fiber 任务队列继续进行上述过程
requestIdleCallback 会让一个低优先级的任务在空闲期被调用
requestAnimationFrame 会让一个高优先级的任务在下一个栈被调用,从而保证了主线程按照优先级执行 fiber 单元
不同类型的任务会被分配不同的优先级,以下是关于优先级的定义:
module.exports = { // heigh levelNoWork: 0, // No work is pending.SynchronousPriority: 1, // For controlled text inputs. TaskPriority: 2, // Completes at the end of the current tick.AnimationPriority: 3, // Needs to complete before the next frame.// low levelHighPriority: 4, // Interaction that needs to complete pretty soon to feel responsive.LowPriority: 5, // Data fetching, or result from updating stores.OffscreenPriority: 6, // Won't be visible but do the work in case it becomes visible.
};
由此我们可以看出Fiber任务的优先级顺序为:
文本框输入 > 本次调度结束需完成的任务 > 动画过渡 > 交互反馈 > 数据更新 > 不会显示但以防将来会显示的任务
渲染阶段(commit):
进入render函数,构建真实的virtualDomTree,React将其所有的变更一次性更新到DOM上。
本文参考并转载于有赞云技术博客:浅谈 React 16 中的 Fiber 机制
https://developers.youzanyun.com/article/1557135472024?p=1&m=0
这篇关于认识react16的fiber架构的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!