详解React Fiber的工作原理

啥是React Fiber?

React Fiber,简单来说就是一个从React v16开始引入的新协调引擎,用来实现Virtual DOM的增量渲染。

说人话:就是一种能让React视图更新过程变得更加流畅顺滑的处理手法。

我们都知道:进程大,线程小。而Fiber(纤维)是一种比线程还要细粒度的处理机制。从这个单词也可以猜测:React Fiber会很“细”。到底怎么个细法,我们接着往下看。

为什么会有React Fiber?

之前说了,React Fiber是为了让React的视图更新过程变得更加流畅顺滑。怎么,之前React的视图更新不流畅,不顺滑了?

还真是的,在React v16之前,React的视图更新确实存在很大的性能问题,其中首当其冲的,就是它的同步更新机制。

在React决定要加载或更新一颗组件树之前,会大致做出如下一系列动作:调用各组件的生命周期函数 --> 计算和对比Virtual DOM --> 更新真实的DOM树。这个过程是同步的,也就是说,一旦这个过程开始,它就会一鼓作气跑完,一直到真实DOM树更新完毕。

然而,当组件树比较庞大时,这种机制的问题就来了:一颗拥有300个组件的组件树需要全部更新,假设一个组件更新只需耗时1ms,整棵树更新一次就需要耗时300ms。在这300ms期间,浏览器的主线程一直在“专心致志”地忙着更新这颗组件树(这时函数的调用栈会非常长),对于页面上的任何操作都是“不闻不问”的。在这期间,假如用户在一个输入框敲了几个字,页面上也不会有任何反应,因为渲染按键输入结果也需要主线程来做,然而此时主线程正忙着更新组件树呢。等到300ms结束了,浏览器主线程有空了,才把刚刚敲的那几个字渲染到input输入框内。

太卡了,真的。

由于JavaScript的单线程工作特点,业内一直有个这样的原则:任何动作都不要长时间霸占主线程,如果迟迟不归还主线程,那么在这期间程序就没法对其他输入作出响应。输入了却没有响应,或者说响应来的很慢,也就是我们常常说的“卡顿”。显然,React的同步更新机制在组件树庞大时就违反了这一原则,犯了大忌。

这就是React Fiber出现的原因:为了解决旧版React视图更新的性能瓶颈。

React Fiber到底怎么工作的?

首先,React Fiber并没有解决更新庞大组件树耗时长的问题,实际上总的耗时还是一样的长。但是它解决了一个被广大开发者口诛笔伐的恶行:长时间霸占主线程不放。

而它解决的方法就是:分片。

它的工作原理是这样的:把耗时长的更新任务拆解成一个个小的任务分片,每执行完一个小的任务分片,都归还一次主线程,看看有没有什么其他紧急任务要做。如果在归还主线程时恰巧发现有紧急任务,那么会马上停掉当前更新任务,转而让主线程去做紧急任务,等主线程做完紧急任务,再重新做更新任务。(注意⚠️:是重新!不是从上次被打断的点继续);如果没有紧急任务,才敢唯唯诺诺地继续做接下来的任务分片。

简单来说,就是降了视图更新的优先级,把更新过程碎片化。

现在我们捋一捋,React Fiber会这样处理一个更新过程:

  1. 将一个更新过程分为Reconciliation阶段和Commit阶段,Reconciliation阶段(调度阶段)会更新数据并生成新的虚拟DOM,并且对新旧的虚拟DOM进行diff,得到需要更新的元素,放到新的更新队列中;而Commit阶段(渲染阶段)则会遍历更新队列,并且将所有的变更一次性更新到真实DOM中;
  2. 对于Reconciliation阶段进行分片处理,这个阶段可以被更紧急的任务打断,分片任务做到一半可能要重来;
  3. 对于Commit阶段,直接一鼓作气把DOM更新完,不能被打断。

React Fiber的实现原理

React Fiber实现的难点有两个:暂停/重启如何实现?任务如何分散执行?

对于前者,暂停/重启意味着我们需要保存状态,这里在实现上用到了具有链表和指针的“单链表树遍历算法”,能够记录遍历过程中的上一步和下一步。

而对于后者,则用到了requestAnimationFramerequestIdelCallback这两个API,其中requestAnimationFrame是浏览器在每一帧都一定会执行的,可以放一些高优先级的任务;而requestIdelCallback则是浏览器在一帧中最后如果有空闲时间才会去执行,可以放一些低优先级的任务,需要polyfill(因为兼容性不佳)。

React Fiber对我们日常开发有什么影响?

React Fiber在Reconciliation阶段可能会调用以下生命周期函数(这也意味着在这个阶段的生命周期函数在一次加载和更新过程中可能会被多次调用):

  • componentWillMount
  • componentWillUpdate
  • componentWillReceiveProps
  • shouldComponentUpdate

如果你恰巧没有上react hooks的车,而是使用传统的类组件进行开发,那么切记,不要在以上几个生命周期函数中做只需要做一次的操作(比如:页面初始化时发起一个ajax请求获取数据)。

如果你平常使用react hooks进行开发,那没事了,就当看了个热闹。

以上就是详解React Fiber的工作原理的详细内容,更多关于React Fiber的工作原理的资料请关注我们其它相关文章!

(0)

相关推荐

  • React Fiber结构的创建步骤

    React Fiber的创建 当前React版本基于V17.0.2版本,本篇主要介绍fiber结构的创建. 一.开始之前 个人理解,如有不对,请指出. 首先需要配置好React的debugger开发环境,入口在这里:github 执行npm run i,安装依赖,npm start运行环境. 二.从React.render开始 通过在项目入口处调用React.render,打上Debug,查看React调用栈. const root = document.getElementById('root

  • 详解React Fiber的工作原理

    啥是React Fiber? React Fiber,简单来说就是一个从React v16开始引入的新协调引擎,用来实现Virtual DOM的增量渲染. 说人话:就是一种能让React视图更新过程变得更加流畅顺滑的处理手法. 我们都知道:进程大,线程小.而Fiber(纤维)是一种比线程还要细粒度的处理机制.从这个单词也可以猜测:React Fiber会很"细".到底怎么个细法,我们接着往下看. 为什么会有React Fiber? 之前说了,React Fiber是为了让React的视

  • 详解JSP 中Spring工作原理及其作用

    详解JSP 中Spring工作原理及其作用 1.springmvc请所有的请求都提交给DispatcherServlet,它会委托应用系统的其他模块负责负责对请求进行真正的处理工作. 2.DispatcherServlet查询一个或多个HandlerMapping,找到处理请求的Controller. 3.DispatcherServlet请请求提交到目标Controller 4.Controller进行业务逻辑处理后,会返回一个ModelAndView 5.Dispathcher查询一个或多个

  • 详解React Fiber架构原理

    目录 一.概述 二.Fiber架构 2.1 执行单元 2.2 数据结构 2.3 Fiber链表结构 2.4 Fiber节点 2.5 API 2.5.1 requestAnimationFrame 2.5.2 requestIdleCallback 三.Fiber执行流程 3.1 render阶段 3.1.1 遍历流程 3.1.2 收集effect list 3.2 commit阶段 3.2.1 根据effect list 更新视图 3.2.2 视图更新 四.总结 一.概述 在 React 16

  • 详解React Hooks是如何工作的

    1. React Hooks VS 纯函数 React Hook 说白了就是 React V18.6 新增的一些 API,API的本质就是提供某种功能的函数接口.因此,React Hooks 就是一些函数,但是 React Hooks 不是纯函数. 什么是纯函数呢?就是此函数在相同的输入值时,需产生相同的输出,并且此函数不能影响到外面的数据. 简单理解就是函数里面不能用到在外面定义的变量,因为如果用到了外面定义的变量,当外面的变量改变时会影响函数内部的计算,函数也会影响到外面的变量. 对于 Re

  • 详解React中Props的浅对比

    上一周去面试的时候,面试官我PureComponent里是如何对比props的,概念已经牢记脑中,脱口而出就是浅对比,接着面试官问我是如何浅对比的,结果我就没回答上来. 趁着周末,再来看看源码里是如何实现的. 类组件的Props对比 类组件是否需要更新需要实现shouldComponentUpdate方法,通常讲的是如果继承的是PureComponent则会有一个默认浅对比的实现. // ReactBaseClasses.js function ComponentDummy() {} Compo

  • 详解React Angular Vue三大前端技术

    一.[React] React(也被称为React.js或ReactJS)是一个用于构建用户界面的JavaScript库.它由Facebook和一个由个人开发者和公司组成的社区来维护. React可以作为开发单页或移动应用的基础.然而,React只关注向DOM渲染数据,因此创建React应用通常需要使用额外的库来进行状态管理和路由,Redux和React Router分别是这类库的例子. 基本用法 下面是一个简单的React在HTML中使用JSX和JavaScript的例子. Greeter函数

  • 一文详解React Redux使用方法

    目录 一.理解JavaScript纯函数 1.1 纯函数的概念 1.2 副作用概念的理解 1.3 纯函数在函数式编程的重要性 二.Redux的核心思想 2.1 为什么需要 Redux 2.2 Redux的核心概念 2.2.1 store 2.2.2 action 2.2.3 reducer 2.3 Redux的三大原则 2.3.1 单一数据源 2.3.2 State是只读的 2.3.3 使用纯函数来执行修改 2.4 Redux 工作流程 三.Redux基本使用 3.1 创建Store的过程 3.

  • 详解React项目的服务端渲染改造(koa2+webpack3.11)

    因为对网页SEO的需要,要把之前的React项目改造为服务端渲染,经过一番调查和研究,查阅了大量互联网资料.成功踩坑. 选型思路:实现服务端渲染,想用React最新的版本,并且不对现有的写法做大的改动,如果一开始就打算服务端渲染,建议直接用NEXT框架来写 项目地址:https://github.com/wlx200510/react_koa_ssr 脚手架选型:webpack3.11.0 + react Router4 + Redux + koa2 + React16 + Node8.x 主要

  • 详解Vue中的MVVM原理和实现方法

    下面由我阿巴阿巴的详细走一遍Vue中MVVM原理的实现,这篇文章大家可以学习到: 1.Vue数据双向绑定核心代码模块以及实现原理 2.订阅者-发布者模式是如何做到让数据驱动视图.视图驱动数据再驱动视图 3.如何对元素节点上的指令进行解析并且关联订阅者实现视图更新 一.思路整理 实现的流程图: 我们要实现一个类MVVM简单版本的Vue框架,就需要实现一下几点: 1.实现一个数据监听Observer,对数据对象的所有属性进行监听,数据发生变化可以获取到最新值通知订阅者. 2.实现一个解析器Compi

  • 详解React中的不可变值

    什么是不可变值 函数式编程是指程序里面的函数和表达式都能像数学中的函数一样,给定了输入值,输出是确定的.比如 let a = 1; let b = a + 1; => a = 1 b = 2; 变量b出现,虽然使用了变量a的值,但是没有修改a的值. 再看我们熟悉的react中的代码,假如初始化了this.state = { count: 1 } componentDidMount() { const newState = { ...state, count: 2 }; // { count: 2

随机推荐