当前位置: 首页 > news >正文

面试官:你是怎样理解Fiber的

hello,这里是潇晨,今天我们来聊一聊Fiber。不知道大家面试的时候有没有遇到过和react Fiber相关的问题呢,这一类问题比较开放,但也是考察对react源码理解深度的问题,如果面试高级前端岗,恰巧你平时用的是react,那这道面试题是你必需要会的一道。

大型应用为什么会慢

那之前的应用为什么会慢呢,传统的前端应用例如js原生或者jquery应用,在构建复杂的大型应用的时候,各种页面之前的相互操作和更新很有可能会引起页面的重绘或重排列,而频繁操作这些dom其实是非常消耗性能的

react源码5.1

在看下图,这是一个节点上的属性,可以看到一个节点上的属性是非常多的,在复杂应用中,操作这些属性的时候可能一不小心就会引起节点大量的更新,那如何提高应用的性能呢?

const div = document.createElement('div');
let str = ''
for(let k in div){str+=','+k
}
console.log(str)

react源码5.2

为什么会出现Fiber

react从15版本开始,到现在的17,以及快出来的18,内部经历了非常大的变化,这一切都是围绕着一个目标进行的,这个目标是异步可中断的更新,而这个目的的最终结果是为了构建快速响应的应用。

复杂应用在更新的时候可能会更新大量的dom,所以react在应用层和dom层之间增加了一层Fiber,而Fiber是在内存中工作的,所以在更新的时候只需要在内存中进行dom更新的比较,最后再应用到需要更新真实节点上

这就引出了一个对比新老节点的过程,而对比两棵树的计算其实是非常消耗性能的,react提出了diff算法来降低对比的复杂度,具体diff的过程可以参考往期文章 diff算法

但是面对越来越复杂的应用,diff算法消耗的时间片还是很长,在没做出优化的情况下,react在进行Fiber的对比和更新节点上的状态的时候依然力不从心,

  • 在react15之前,这个对比的过程被称之为stack reconcile,它的对比方式是‘一条路走到黑’,也就是说这个对比的过程是不能被中断的,这会出现什么情况呢,比如在页面渲染一个比较消耗性能操作,如果这个时候如果用户进行一些操作就会出现卡顿,应用就会显得不流畅。
  • react16之后出现了scheduler,以及react17的Lane模型,它们可以配合着工作,将比较耗时的任务按照Fiber节点划分成工作单元,并且遍历Fiber树计算或者更新节点上的状态可以被中断、继续,以及可以被高优先级的任务打断,比如用户触发的更新就是一个高优先级的任务,高优先级的任务优先执行,应用就不会太卡顿。

什么是Fiber

这就是react所要做的事情了,react创新的提出了jsx,声明式地描述页面呈现的效果,jsx会被babel经过ast解析成React.createElement,而React.createElement函数执行之后就是jsx对象或者说是virtual-dom

  • 在mount的时候,也就是首次渲染的时候,render阶段会根据jsx对象生成新的Fiber节点,然后这些Fiber节点会被标记成带有‘Placement’的副作用,说明它们是新增的节点,需要被插入到真实节点中,在commit阶段就会操作真实节点,将它们插入到dom树中。
  • 在update的时候,也就是应用触发更新的时候,render阶段会根据最新的jsx和老的Fiber进行对比,生成新的Fiber,这些Fiber会带有各种副作用,比如‘Deletion’、‘Update’、‘Placement’等,这一个对比的过程就是diff算法 ,在commit阶段会操作真实节点,执行相应的副作用。

如果对render阶段和commit阶段不了解的可以查看往期文章

8.render阶段

10.commit阶段

react源码3.1

Fiber有比较多的含义,他可以从以下几个角度理解:

  • 工作单元 任务分解 :Fiber最重要的功能就是作为工作单元,保存原生节点或者组件节点对应信息(包括优先级),这些节点通过指针的形似形成Fiber树

  • 增量渲染:通过jsx对象和current Fiber的对比,生成最小的差异补丁,应用到真实节点上

  • 根据优先级暂停、继续、排列优先级:Fiber节点上保存了优先级,能通过不同节点优先级的对比,达到任务的暂停、继续、排列优先级等能力,也为上层实现批量更新、Suspense提供了基础

  • **保存状态:**因为Fiber能保存状态和更新的信息,所以就能实现函数组件的状态更新,也就是hooks

    相关参考视频讲解:进入学习

Fiber的数据结构

Fiber的自带的属性如下:

//ReactFiber.old.js
function FiberNode(tag: WorkTag,pendingProps: mixed,key: null | string,mode: TypeOfMode,
) {//作为静态的数据结构 保存节点的信息 this.tag = tag;//对应组件的类型this.key = key;//key属性this.elementType = null;//元素类型this.type = null;//func或者classthis.stateNode = null;//真实dom节点//作为fiber数架构 连接成fiber树this.return = null;//指向父节点this.child = null;//指向childthis.sibling = null;//指向兄弟节点this.index = 0;this.ref = null;//用作为工作单元 来计算statethis.pendingProps = pendingProps;this.memoizedProps = null;this.updateQueue = null;this.memoizedState = null;this.dependencies = null;this.mode = mode;//effect相关this.effectTag = NoEffect;this.nextEffect = null;this.firstEffect = null;this.lastEffect = null;//优先级相关的属性this.lanes = NoLanes;this.childLanes = NoLanes;//current和workInProgress的指针this.alternate = null;
}

Fiber是怎样工作的

现在我们知道了Fiber可以保存真实的dom,真实dom对应在内存中的Fiber节点会形成Fiber树,这颗Fiber树在react中叫current Fiber,也就是当前dom树对应的Fiber树,而正在构建Fiber树叫workInProgress Fiber,这两颗树的节点通过alternate相连.

function App() {return (<><h1><p>count</p> xiaochen</h1></>)
}ReactDOM.render(<App />, document.getElementById("root"));

react源码7.2

构建workInProgress Fiber发生在createWorkInProgress中,它能创建或者服用Fiber

//ReactFiber.old.js
export function createWorkInProgress(current: Fiber, pendingProps: any): Fiber {let workInProgress = current.alternate;if (workInProgress === null) {//区分是在mount时还是在update时workInProgress = createFiber(current.tag,pendingProps,current.key,current.mode,);workInProgress.elementType = current.elementType;workInProgress.type = current.type;workInProgress.stateNode = current.stateNode;workInProgress.alternate = current;current.alternate = workInProgress;} else {workInProgress.pendingProps = pendingProps;//复用属性workInProgress.type = current.type;workInProgress.flags = NoFlags;workInProgress.nextEffect = null;workInProgress.firstEffect = null;workInProgress.lastEffect = null;//...}workInProgress.childLanes = current.childLanes;//复用属性workInProgress.lanes = current.lanes;workInProgress.child = current.child;workInProgress.memoizedProps = current.memoizedProps;workInProgress.memoizedState = current.memoizedState;workInProgress.updateQueue = current.updateQueue;const currentDependencies = current.dependencies;workInProgress.dependencies =currentDependencies === null? null: {lanes: currentDependencies.lanes,firstContext: currentDependencies.firstContext,};workInProgress.sibling = current.sibling;workInProgress.index = current.index;workInProgress.ref = current.ref;return workInProgress;
}
  • 在mount时:会创建fiberRoot和rootFiber,然后根据jsx对象创建Fiber节点,节点连接成current Fiber树。
    react源码7.1

  • 在update时:会根据新的状态形成的jsx(ClassComponent的render或者FuncComponent的返回值)和current Fiber对比形(diff算法)成一颗叫workInProgress的Fiber树,然后将fiberRoot的current指向workInProgress树,此时workInProgress就变成了current Fiber。fiberRoot:指整个应用的根节点,只存在一个

    fiberRoot:指整个应用的根节点,只存在一个

    rootFiber:ReactDOM.render或者ReactDOM.unstable_createRoot创建出来的应用的节点,可以存在多个。

    我们现在知道了存在current Fiber和workInProgress Fiber两颗Fiber树,Fiber双缓存指的就是,在经过reconcile(diff)形成了新的workInProgress Fiber然后将workInProgress Fiber切换成current Fiber应用到真实dom中,存在双Fiber的好处是在内存中形成视图的描述,在最后应用到dom中,减少了对dom的操作。

现在来看看Fiber双缓存创建的过程图

  • mount时:

    1. 刚开始只创建了fiberRoot和rootFiber两个节点
      react源码7.6
    2. 然后根据jsx创建workInProgress Fiber:
      react源码7.7
    3. 把workInProgress Fiber切换成current Fiber
      react源码7.8
  • update时

    1. 根据current Fiber创建workInProgress Fiber
      react源码7.9
    2. 把workInProgress Fiber切换成current Fiber

react源码7.8

为什么Fiber能提升效率

Fiber是一个js对象,能承载节点信息、优先级、updateQueue,同时它还是一个工作单元。

  1. Fiber双缓存可以在构建好wip Fiber树之后切换成current Fiber,内存中直接一次性切换,提高了性能
  2. Fiber的存在使异步可中断的更新成为了可能,作为工作单元,可以在时间片内执行工作,没时间了交还执行权给浏览器,下次时间片继续执行之前暂停之后返回的Fiber
  3. Fiber可以在reconcile的时候进行相应的diff更新,让最后的更新应用在真实节点上

相关文章:

面试官:你是怎样理解Fiber的

hello&#xff0c;这里是潇晨&#xff0c;今天我们来聊一聊Fiber。不知道大家面试的时候有没有遇到过和react Fiber相关的问题呢&#xff0c;这一类问题比较开放&#xff0c;但也是考察对react源码理解深度的问题&#xff0c;如果面试高级前端岗&#xff0c;恰巧你平时用的是re…...

【C++的OpenCV】第一课-opencv的介绍和安装(Linux环境下)

第一课-目录一、基本介绍1.1 官网1.2 git源码1.3 介绍二、OpenCV的相关部署工作2.1 Linux平台下部署OpenCV一、基本介绍 1.1 官网 opencv官网 注意&#xff1a;官网为英文版本&#xff0c;可以使用浏览器自带的翻译插件进行翻译&#xff0c;真心不推荐大家去看别人翻译的&am…...

k8s安装tekton,编写task

文章目录一、官方安装二、国内资源安装安装tekton安装dashboard安装CLI三、demo编写task.yaml编写taskRun.yaml使用tkn命令查看参考文章一、官方安装 地址&#xff1a;https://tekton.dev/docs/installation/pipelines/#installing-tekton-pipelines-on-kubernetes 注意&#…...

K_A12_014 基于STM32等单片机驱动S12SD紫外线传感器模块 串口与OLED0.96双显示

K_A12_014 基于STM32等单片机驱动S12SD紫外线传感器模块 串口与OLED0.96双显示一、资源说明二、基本参数参数引脚说明三、驱动说明IIC地址/采集通道选择/时序对应程序:数据对比&#xff1a;四、部分代码说明1、接线引脚定义1.1、STC89C52RCS12SD紫外线传感器模块1.2、STM32F103…...

还真不错,今天 Chatgpt 教会我如何开发一款小工具开发(Python 代码实现)

上次使用 Chatgpt 写爬虫&#xff0c;虽然写出来的代码很多需要修改后才能运行&#xff0c;但Chatgpt提供的思路和框架都是没问题。 这次让 Chatgpt 写一写GUI程序&#xff0c;也就是你常看到的桌面图形程序。 由于第一次测试&#xff0c;就来个简单点的&#xff0c;用Python…...

Boom 3D最新版本下载电脑音频增强应用工具

为了更好地感受音乐的魅力&#xff0c;Boom 3D 可以让你对音效进行个性化增强&#xff0c;并集成 3D 环绕立体声效果&#xff0c;可以让你在使用任何耳机时&#xff0c;都拥有纯正、优质的音乐体验。Boom 3D是一款充满神奇魅力的3D环绕音效升级版&#xff0c;BOOM 3D是一个全新…...

redis-如何保证数据库和缓存双写一致性?

前言 数据库和缓存&#xff08;比如&#xff1a;redis&#xff09;双写数据一致性问题&#xff0c;是一个跟开发语言无关的公共问题。尤其在高并发的场景下&#xff0c;这个问题变得更加严重。 我很负责的告诉大家&#xff0c;该问题无论在面试&#xff0c;还是工作中遇到的概率…...

系列二、核心概念运行流程

一、镜像&容器&仓库 1.1、镜像 定义&#xff1a;一个镜像代表着一个软件&#xff0c;例如&#xff1a;mysql镜像、redis镜像、nginx镜像。 特点&#xff1a;只读 1.2、容器 定义&#xff1a;基于某个镜像运行一次就会生成一个程序实例&#xff0c;一个程序实例称之为一…...

恢复 iPhone 和 iPad 数据的 10 种简单工具

它发生了.. 有时您需要从您的手机或平板设备恢复重要数据。 许多人已经开始将重要文件存储在手机上&#xff0c;因为他们几乎可以在任何情况下随时随地轻松访问数据。 从技术上讲&#xff0c;您会在几分之一秒内丢失所有存储的信息、照片、视频、音乐、文档等。因此&#xff…...

经理与员工工资关系-课后程序(JAVA基础案例教程-黑马程序员编著-第四章-课后作业)

【案例4-6】经理与员工工资案例&#xff08;利用多态实现&#xff09; 欢迎点赞关注收藏 【案例介绍】 案例描述 某公司的人员分为员工和经理两种&#xff0c;但经理也属于员工中的一种&#xff0c;公司的人员都有自己的姓名和地址&#xff0c;员工和经理都有自己的工号、工…...

Micropython ESP32配置与烧录版本

下载ESP32的Micropython固件 官方连接https://www.micropython.org/download/esp32/ 看了下描述&#xff0c;上面的是IDF4.x系列编译&#xff0c;下面是IDF3.x系列编译&#xff0c;我们默认选新的 下载安装CP2102驱动 CP210x USB to UART Bridge VCP Drivers - Silicon Labs…...

java面试题-并发关键字(Synchronized,volatile,final)

Synchronized1.Synchronized可以作用在哪里?Synchronized可以作用在方法、代码块、静态方法和类上。方法public synchronized void method(){//同步代码块 }代码块Object lock new Object(); synchronized(lock){//同步代码块 }静态方法public static synchronized void stat…...

【笔试强训】Day_02

目录 一、选择题 1、 2、 3、 4、 5、 6、 7、 8、 9、 10、 二、编程题 1、排序子序列 2、倒置字符串 一、选择题 1、 使用printf函数打印一个double类型的数据&#xff0c;要求&#xff1a;输出为10进制&#xff0c;输出左对齐30个字符&#xff0c;4位精度。…...

DepGraph:适用任何结构的剪枝

文章目录摘要1、简介2、相关工作3、方法3.1、神经网络中的依赖关系3.2、依赖关系图3.3、使用依赖图剪枝4、实验4.1、设置。4.2、CIFAR的结果4.3、消融实验4.4、适用任何结构剪枝5、结论摘要 论文链接&#xff1a;https://arxiv.org/abs/2301.12900 源码&#xff1a;https://gi…...

【结构体版】通讯录

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前是C语言学习者 ✈️专栏&#xff1a;项目 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章对你有帮助的话 欢迎 评论&#x1f4ac; 点赞&#x…...

Debezium系列之:基于debezium采集数据到kafka,再从kafka将数据流式传输到下游数据库

Debezium系列之:基于debezium采集数据到kafka,再从kafka将数据流式传输到下游数据库 一、需求背景二、准备Debezium集群和相关jar包的详细步骤三、查看插件是否加载成功四、源数据库表结构五、根据源数据库表结构准备目标数据库的表六、基于debezium采集数据到kafka七、查看c…...

【2023】华为OD机试真题Java-题目0217-上班之路

上班之路 题目描述 Jungle生活在美丽的蓝鲸城,大马路都是方方正正,但是每天马路的封闭情况都不一样。 地图由以下元素组成: . — 空地,可以达到;* — 路障,不可达到;S — Jungle的家;T — 公司. 其中我们会限制Jungle拐弯的次数,同时Jungle可以清除给定个数的路障,现在…...

基于spring生态的基础后端开发及渗透测试流程(二)

基于spring生态的基础后端开发及渗透测试流程&#xff08;二&#xff09;安全设备IDS蜜罐安全加固渗透测试信息收集子域名域名注册信息企业信息端口扫描源码泄露路径扫描真实ip探测js扫描设备检测蜜罐识别waf识别社工爆破漏洞扫描系统扫描web扫描应急响应继上次写了一份基于spr…...

Python语言零基础入门教程(二十六)

Python OS 文件/目录方法 Python语言零基础入门教程&#xff08;二十五&#xff09; 51、Python os.stat_float_times() 方法 概述 os.stat_float_times() 方法用于决定stat_result是否以float对象显示时间戳。 语法 stat_float_times()方法语法格式如下&#xff1a; os.s…...

人们最想看到的是:你在坚持什么?

【人们最想看到的是&#xff1a;你在坚持什么】 长远规划才能对抗不确定性 品牌也能够对抗不确定性 想想这么多年东搞搞&#xff0c;西搞搞 最后缺乏正向积累的【厚度】 趣讲大白话&#xff1a;把每滴水尽量接到碗里 人吃的是饭&#xff0c;拉出来的是信息 *********** 人们在频…...

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

【Oracle APEX开发小技巧12】

有如下需求&#xff1a; 有一个问题反馈页面&#xff0c;要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据&#xff0c;方便管理员及时处理反馈。 我的方法&#xff1a;直接将逻辑写在SQL中&#xff0c;这样可以直接在页面展示 完整代码&#xff1a; SELECTSF.FE…...

边缘计算医疗风险自查APP开发方案

核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...

跨链模式:多链互操作架构与性能扩展方案

跨链模式&#xff1a;多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈&#xff1a;模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展&#xff08;H2Cross架构&#xff09;&#xff1a; 适配层&#xf…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”&#xff0c;物流的终极形态正在诞生 想象这样的场景&#xff1a; 凌晨3点&#xff0c;某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径&#xff1b;AI视觉系统在0.1秒内扫描包裹信息&#xff1b;数字孪生平台正模拟次日峰值流量压力…...

全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比

目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec&#xff1f; IPsec VPN 5.1 IPsec传输模式&#xff08;Transport Mode&#xff09; 5.2 IPsec隧道模式&#xff08;Tunne…...

rnn判断string中第一次出现a的下标

# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)

推荐 github 项目:GeminiImageApp(图片生成方向&#xff0c;可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

莫兰迪高级灰总结计划简约商务通用PPT模版

莫兰迪高级灰总结计划简约商务通用PPT模版&#xff0c;莫兰迪调色板清新简约工作汇报PPT模版&#xff0c;莫兰迪时尚风极简设计PPT模版&#xff0c;大学生毕业论文答辩PPT模版&#xff0c;莫兰迪配色总结计划简约商务通用PPT模版&#xff0c;莫兰迪商务汇报PPT模版&#xff0c;…...

未授权访问事件频发,我们应当如何应对?

在当下&#xff0c;数据已成为企业和组织的核心资产&#xff0c;是推动业务发展、决策制定以及创新的关键驱动力。然而&#xff0c;未授权访问这一隐匿的安全威胁&#xff0c;正如同高悬的达摩克利斯之剑&#xff0c;时刻威胁着数据的安全&#xff0c;一旦触发&#xff0c;便可…...