对Fiber架构的理解?解决了什么问题?

2023-11-18

一、问题

JavaScript引擎和页面渲染引擎两个线程是互斥的,当其中一个线程执行时,另一个线程只能挂起等待

如果 JavaScript 线程长时间地占用了主线程,那么渲染层面的更新就不得不长时间地等待,界面长时间不更新,会导致页面响应度变差,用户可能会感觉到卡顿

而这也正是 React 15 的 Stack Reconciler所面临的问题,当 React在渲染组件时,从开始到渲染完成整个过程是一气呵成的,无法中断

如果组件较大,那么js线程会一直执行,然后等到整棵VDOM树计算完成后,才会交给渲染的线程

这就会导致一些用户交互、动画等任务无法立即得到处理,导致卡顿的情况

二、是什么

React Fiber 是 Facebook 花费两年余时间对 React 做出的一个重大改变与优化,是对 React 核心算法的一次重新实现。从Facebook在 React Conf 2017 会议上确认,React Fiber 在React 16 版本发布

react中,主要做了以下的操作:

  • 为每个增加了优先级,优先级高的任务可以中断低优先级的任务。然后再重新,注意是重新执行优先级低的任务
  • 增加了异步任务,调用requestIdleCallback api,浏览器空闲的时候执行
  • dom diff树变成了链表,一个dom对应两个fiber(一个链表),对应两个队列,这都是为找到被中断的任务,重新执行

从架构角度来看,Fiber 是对 React核心算法(即调和过程)的重写

从编码角度来看,Fiber是 React内部所定义的一种数据结构,它是 Fiber树结构的节点单位,也就是 React 16 新架构下的虚拟DOM

一个 fiber就是一个 JavaScript对象,包含了元素的信息、该元素的更新操作队列、类型,其数据结构如下:

type Fiber = {
  // 用于标记fiber的WorkTag类型,主要表示当前fiber代表的组件类型如FunctionComponent、ClassComponent等
  tag: WorkTag,
  // ReactElement里面的key
  key: null | string,
  // ReactElement.type,调用`createElement`的第一个参数
  elementType: any,
  // The resolved function/class/ associated with this fiber.
  // 表示当前代表的节点类型
  type: any,
  // 表示当前FiberNode对应的element组件实例
  stateNode: any,

  // 指向他在Fiber节点树中的`parent`,用来在处理完这个节点之后向上返回
  return: Fiber | null,
  // 指向自己的第一个子节点
  child: Fiber | null,
  // 指向自己的兄弟结构,兄弟节点的return指向同一个父节点
  sibling: Fiber | null,
  index: number,

  ref: null | (((handle: mixed) => void) & { _stringRef: ?string }) | RefObject,

  // 当前处理过程中的组件props对象
  pendingProps: any,
  // 上一次渲染完成之后的props
  memoizedProps: any,

  // 该Fiber对应的组件产生的Update会存放在这个队列里面
  updateQueue: UpdateQueue<any> | null,

  // 上一次渲染的时候的state
  memoizedState: any,

  // 一个列表,存放这个Fiber依赖的context
  firstContextDependency: ContextDependency<mixed> | null,

  mode: TypeOfMode,

  // Effect
  // 用来记录Side Effect
  effectTag: SideEffectTag,

  // 单链表用来快速查找下一个side effect
  nextEffect: Fiber | null,

  // 子树中第一个side effect
  firstEffect: Fiber | null,
  // 子树中最后一个side effect
  lastEffect: Fiber | null,

  // 代表任务在未来的哪个时间点应该被完成,之后版本改名为 lanes
  expirationTime: ExpirationTime,

  // 快速确定子树中是否有不在等待的变化
  childExpirationTime: ExpirationTime,

  // fiber的版本池,即记录fiber更新过程,便于恢复
  alternate: Fiber | null,
}

三、如何解决

Fiber把渲染更新过程拆分成多个子任务,每次只做一小部分,做完看是否还有剩余时间,如果有继续下一个任务;如果没有,挂起当前任务,将时间控制权交给主线程,等主线程不忙的时候在继续执行

即可以中断与恢复,恢复后也可以复用之前的中间状态,并给不同的任务赋予不同的优先级,其中每个任务更新单元为 React Element 对应的 Fiber节点

实现的上述方式的是requestIdleCallback方法

window.requestIdleCallback()方法将在浏览器的空闲时段内调用的函数排队。这使开发者能够在主事件循环上执行后台和低优先级工作,而不会影响延迟关键事件,如动画和输入响应

首先 React 中任务切割为多个步骤,分批完成。在完成一部分任务之后,将控制权交回给浏览器,让浏览器有时间再进行页面的渲染。等浏览器忙完之后有剩余时间,再继续之前 React 未完成的任务,是一种合作式调度。

该实现过程是基于 Fiber节点实现,作为静态的数据结构来说,每个 Fiber 节点对应一个 React element,保存了该组件的类型(函数组件/类组件/原生组件等等)、对应的 DOM 节点等信息。

作为动态的工作单元来说,每个 Fiber 节点保存了本次更新中该组件改变的状态、要执行的工作。

每个 Fiber 节点有个对应的 React element,多个 Fiber节点根据如下三个属性构建一颗树:

// 指向父级Fiber节点
this.return = null
// 指向子Fiber节点
this.child = null
// 指向右边第一个兄弟Fiber节点
this.sibling = null
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

对Fiber架构的理解?解决了什么问题? 的相关文章

  • 禁用浏览器状态栏文本

    背景 现代浏览器取消了经典的状态栏 而是在窗口底部绘制一个小工具提示 在悬停 焦点时显示链接目标 下面的屏幕截图说明了这种行为的示例 在我的例子中是不需要的 问题 有没有一种可移植的方法来禁用这些工具提示 在我的特殊情况下 我是否遗漏了这样
  • 在文件之间共享变量(没有全局变量)

    据我了解 使用创建的变量let在 Javascript 中不能是全局的 我thought这意味着该变量仅存在于该特定文件中 然而 当我做一个简单 人为的例子时 A js let a 5 B js console log a 索引 html
  • 在一段时间内切换(或闪烁)表中的特定单元格

    我已经在 Html 中创建了一个表格 我想让一个特定的单元格闪烁 打开和关闭 您能否让我知道是否可以使用 javascript h4 Two rows and three columns h4 table border 1 width 10
  • 直接加载页面到锚标记

    当我加载 URL 中带有哈希标记的页面时 页面会加载 然后跳转到锚标记 有没有什么方法可以防止这种 跳转 要么直接将页面加载到锚标记 要么至少使滚动平滑 我在 Chrome 和 Firefox 中看到这个问题 但在 IE 中没有 如果你仍然
  • Ace编辑器使用javascript触发事件

    有没有类似的东西 editor getSession trigger change 我想要这个的原因是因为编辑器进出新的 所以当它返回视图时我需要它做正常的 更改 事情 但我不想等待用户输入 目前我有 editor getSession o
  • GWT 与 ScriptSharp 的优缺点 [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • Material UI v1.0.0 如何重写Stepper类来设置图标大小

    我现在正在迁移到新版本的 Material UI 我不得不说我有点困惑如何覆盖类 我需要使用Stepper https material ui next com demos stepper 使用替代标签 它对我有用 我能够覆盖根类来设置透明
  • YouTube iframe 不响应 postMessage 命令

    我正在尝试使用来自父级的 postMessage 命令来控制 YouTube iframe 但它似乎不起作用 由于多种原因 我没有使用 YouTube API 只是使用带有 YouTube 嵌入视频的普通 iframe 我尝试发送命令的方式
  • 如何获得日期为 yyyy-mm-dd 的年份差异?

    我想得到以 yyyy mm dd 格式给出的两个日期之间的差异 差异应该是年份 var ds 2002 09 23 var today date new Date alert today date Date prototype yyyymm
  • 使用useReducer时如何避免耦合?

    为了防止将回调传递给我正在使用的子组件useReducer反而 这避免了子组件在每个父渲染上重新渲染的问题 但缺点似乎是父组件和子组件之间的紧密耦合 通过紧密耦合 我的意思是子级需要明确了解父级定义的减速器所期望的操作的形状 例如 想象一个
  • 如何在android中使用webview明智地显示Html内容页面?

    您好 我创建了一个简单的应用程序来在 webview 中显示 html 页面 我使用 webview 并显示页面加载时间 如下所示 此后禁用滚动并使用下一个和上一个按钮来后退和前进包含 所以我的代码如下 首先onCreate显示添加webv
  • ASP.Net Web 应用程序 Jquery Photoviewer 和 Ajaxical 更新

    有一个错误我的网站 http new mnarfezhom com 请进入右数第三个菜单 有些图像只能通过 jquery photoviewer 显示 onlclick 这很好用 现在 当我单击页面底部的 Ajaxical 更新按钮时 问题
  • 如何查看远程脚本被阻止时返回的内容

    我在我的 web 应用程序中使用 Google 托管的 jQuery ajax googleapis com ajax libs jquery 1 8 3 jquery min js 作为错误诊断的一部分 我有一个 window onerr
  • 数据与线的日期和时间转换

    我使用 D3 V5 创建了此图表 另外 我已在小提琴上附加了示例数据 您可以点击此处查看 https plnkr co edit pINxcS9yt9AuJmSk02Fs p preview 我已经包括了tick函数代码块 它在向左滑动的路
  • 将数组中的项目移动到最后一个位置

    我有一系列对象 我想将选定的对象移动到数组中的最后一个位置 我如何在 javascript 或 jquery 中执行此操作 这是我的一些代码 var sortedProductRow this product row for var s i
  • FB.logout() - 无访问令牌 - “以不同用户身份登录”

    这个问题与这个问题相关 在没有访问令牌的情况下调用 FB logout https stackoverflow com questions 8430474 fb logout called without an access token 1
  • 如何在 Mongoose 中设置文档创建的 TTL 日期?

    我正在尝试做一个promoCodeMongoose 中的架构 创建时 我需要能够设置促销代码的到期日期 促销代码不一定相同TTL 我在看这个问题 https stackoverflow com questions 14597241 sett
  • 返回深度嵌套数组中对象的索引的函数

    我可能需要编写一个函数 仅输出数组内对象的索引 显然 使用 inArray 在下面的示例中返回这个索引就可以了 array one two three inArray one array 0 对于更复杂的数组 如何找到嵌套对象的索引 arr
  • Firefox 中的代理设置不会“粘连”

    在家里我们有一个代理服务器 在工作中我们不会 Firefox 在这方面令人恼火 每当我启动它时 它都会默认使用代理服务器 如果我执行 工具 gt 选项 gt 设置 并选择 无代理 则没有问题 但是 如果我关闭 Firefox 并重新启动它
  • 反应光滑的幻灯片高度问题

    我无法让这些 React Slick 滑块组件达到相同的高度 它们都是响应式 div 并随着页面大小的变化相应地调整大小 但理想情况下 我希望左侧的 div 与右侧的 div 具有相同的高度 我使用下面的代码片段定义了 SimpleSlid

随机推荐

  • JQuery中&(‘#form‘).serialize()方法失效

    JQuery中serialize方法失效 要按照以下步骤检查 1 id是不是重名 2 hidden和display none设置以后 元素并不会被序列化 后台也无法获取 检查是不是有这个属性 3 form标签中的input标签中id和nam
  • 极简短网址链接生成系统网站源码

    极简短网址链接生成系统 前两年流行的新浪短网址和一些小站长搭建的短网址基本都gg了 想要一个既稳定又好用的短网址系统只有自己搭建了 今天给大家分享一个很好用的短网址系统 本系统是国内程序员开发 后台简洁 适合自用 安装教程 1 上传源码并解
  • .net下用c# 编写成语字典查询工具

    呵呵 以前弄的一个成语字典数据库 最近用C 写了个查询工具 界面 源代码如下 http blog csdn net greenerycn 请遵守署名非商业的CC版权 using System using System Collections
  • 【往届均已检索】2023年控制理论与应用国际会议(ICoCTA 2023)

    往届均已检索 2023年控制理论与应用国际会议 ICoCTA 2023 重要信息 会议网址 www icocta org 会议时间 2023年10月20 22日 召开地点 福建 厦门 截稿时间 2023年8月30日 录用通知 投稿后2周内
  • 时间格式2019-06-27T16:00:00.000Z转换为北京时间

    时间的描述 UTC 国际时间 UTC 8 伦敦时间 UTC 8就是国际时加八小时 是东八区时间 也就是北京时间 String dateTime 2019 06 27T16 00 00 000Z dateTime dateTime repla
  • 让ChatGPT帮你写一个剧情脚本

    最近 很多视频制作者正在使用AI编写视频脚本 效率直接提升20倍以上 而ChatGPT作为一个强大的AI模型 在各个领域都得到了广泛应用 尽管对于ChatGPT的介绍不是很多 但是它已经在很多自媒体平台上被广泛利用来处理工作了 如果你想学习
  • 激活函数及其各自的优缺点

    原文链接 感谢原作者 温故知新 激活函数及其各自的优缺点 1 什么是激活函数 所谓激活函数 Activation Function 就是在人工神经网络的神经元上运行的函数 负责将神经元的输入映射到输出端 激活函数对于人工神经网络模型去学习
  • 整体学习法之信息分类

    在学习的时候 我们都是有一个流程 获取信息 gt 理解信息 gt 扩展信息 gt 纠正信息 gt 应用信息 信息分成以下几类 随意信息 比如太阳半径多少 苹果的价格这些 都是一些毫无规律的东西 这些就是靠机械记忆 几乎不需要什么处理 也没有
  • [YOLO专题-16]:YOLO V5 - 如何把labelme json训练数据集批量转换成yolo数据集

    作者主页 文火冰糖的硅基工坊 文火冰糖 王文兵 的博客 文火冰糖的硅基工坊 CSDN博客 本文网址 https blog csdn net HiWangWenBing article details 122334367 目录 前言 第1章
  • Java高级开发工程师面试题汇总

    面试主要涉及到的技术点 概述 以Java编程基础 JVM原理 Spring Spring Boot Redis Zookeeper 消息队列 Kafka Rocket MQ MySQL等为主 也包括Dubbo Tomcat性能优化 容器化技
  • 被腾讯云的AI绘画整破防了

    购买 618活动 贪便宜29 9买了个腾讯云的AI绘画 问题 主要遇到了两个问题 整破防了兄弟们 1 文档问题 只封装了请求之后获取base64格式的图片 没有封装如何从base64转换成图片展示出来 这个还需要自己去开发 2 sdk 安装
  • mysql 续行符_继续字符集——「一个命令行搞懂Mysql字符集」

    其实我纠结挺久 要不要写这一篇文章 不怎么想让大家感觉我好像只会字符集一样 Mysql在数据的存储上 提供了不同的字符集支持 在数据的比对上 又提供了不同的字符序支持 与Oracle实例级别的设置不同 Mysql很灵活 它提供了不同级别的设
  • 蓝桥杯算法训练VIP-求先序排列

    题目 题目链接 题解 递归 首先要了解什么是先序遍历 中序遍历和后序遍历 大佬讲解树的遍历 一般同学们应该都知道如何遍历 这个题有点像模拟实现题 就是把你手算的过程实现一遍 整体思路 先从后序遍历中确定根 再去中序遍历中找到根的左右两侧的子
  • 超线程技术

    超线程 HT Hyper Threading 是英特尔研发的一种技术 于2002年发布 超线程技术原先只应用于Xeon 处理器中 当时称为 Super Threading 之后陆续应用在Pentium 4 HT中 早期代号为Jackson
  • 字体图标的使用方式

    字体图标的使用 无论用哪种方法 咋们首先都得引入文件 如何使用字体图标呢 首先咋们要先了解到一个东西 这个东西就是字体图标库 https www iconfont cn 字体图标有四种引入方式 无论何种引入方式 都要先下载本地字体包 引入c
  • Anaconda Navigator打不开 This application failed to start because it could not find or load the QT ....

    anaconda Navigator打不开 直接弹出错误窗口 在网上试了很多方法都没有成功 折腾了好久 卸载重装还是一样的错误 手动添加过如下的环境变量 网上有的人成功了但是我没有 还是报错 下面分享以下我最后解决的方法给大家参考 1 删除
  • 多元有序logistic回归_stata速学

    NO 07 ZEYI 06 2020 正文共 2010字 28图 预计阅读时间 6分钟 嘿喽 我是则已 这是stata的第七期学习 前面学习了最小二乘回归分析 非线性回归分析都要求因变量是连续变量 但很多时候因变量是离散的 即1就是1 2就
  • CUDA使用结构体传输时出现写入位置的访问冲突

    这是我的之前写的关于在CUDA中传输结构体的代码 CUDA结构体传输 include cuda runtime h include device launch parameters h include
  • 混合分布(mixture distribution)

    文章目录 1 基本概念 2 基本性质 1 基本概念 在概率与统计中 如果我们有一个包含多个随机变量的随机变量集合 再基于该集合生成一个新的随机变量 则该随机变量的分布称为混合分布 mixture distribution 具体来说 首先 根
  • 对Fiber架构的理解?解决了什么问题?

    一 问题 JavaScript引擎和页面渲染引擎两个线程是互斥的 当其中一个线程执行时 另一个线程只能挂起等待 如果 JavaScript 线程长时间地占用了主线程 那么渲染层面的更新就不得不长时间地等待 界面长时间不更新 会导致页面响应度