React源码分析(一)Fiber
前言
本次React源码参考版本为17.0.3
。
React架构前世今生
查阅文档了解到, React@16.x
是个分水岭。
React@15及之前
在16之前,React架构大致可以分为两层:
- Reconciler: 主要职责是对比查找更新前后的变化的组件;
- Renderer: 主要职责是基于变化渲染页面;
但是React团队意识到这样的架构有致命问题: 因为在React15中,组件的更新是基于递归查找实现的,这样一旦开始递归,是没有办法中断的,如果组件层级很深,就会出现性能问题,导致页面卡顿。
React@16及之后
为了解决这样的问题,React团队在React@16
进行了重构,引入了新的架构模型:
- Reconciler: 主要职责是对比查找更新前后的变化的组件;
- Renderer: 主要职责是基于变化渲染页面;
- Scheduler: 主要职责是区分任务优先级,优先执行高优先级的任务;
新的架构在原来的基础上引入了Scheduler(调度器)
,这个东西是React团队参考浏览器的API:requestIdleCallback
实现的。它的主要作用就是调度更新任务:
- 一方面可以中断当前任务执行更高优先级的任务;
- 另一方面能判断浏览器空闲时间,在恰当的时间将主动权给到浏览器,保证页面性能;并在浏览器下次空闲时继续之前中断的任务; 这样就将之前的不可中断的同步更新变成了异步可中断更新,不直接使用浏览器API可能考虑到兼容问题,可能也有别的方面的考量。
下面是新的React架构更新模型:
这个新的架构在进入Renderer之前的流程是可以被中断的,主要有下列两种情况:
- 进入了更高优先级的任务;
- 浏览器在当前帧没有剩余空闲时间了;
Fiber
Fiber简单的理解就是React15
版本的虚拟DOM。
Fiber简单理解
如果将新的React架构比作一个公司,Fiber在新的架构里承担的就是这个公司的员工,员工也有等级,老板,部长,基层,每个人有自己的职责,知道自己在哪个节点该做什么工作,并将未完成的工作记住等第二天上班继续完成,从而保证公司的顺利运行。而每个Fiber对应一个React element
:
假如有这样一段代码:
function App() {return (<div><span>牛牛</span><span>不怕困难</span></div>)
}
上面的代码的抽象Fiber树:
其中的每个方块都是一个Fiber,它们通过
child, return, sibling
连接对方构成一个Fiber树。
Fiber结构
来看一个Fiber会有哪些属性:
function FiberNode(tag, pendingProps, key, mode) {// Instancethis.tag = tag; // 组件类型this.key = key; // 组件props上的keythis.elementType = null; // ReactElement.type 组件的dom类型, 比如`div, p`this.type = null; // 异步组件resolved之后返回的内容this.stateNode = null; // 在浏览器环境对应dom节点this.return = null; // 指向父节点this.child = null; // 孩子节点this.sibling = null; // 兄弟节点, 兄弟节点的return指向同一个父节点this.index = 0;this.ref = null; // refthis.pendingProps = pendingProps; // 新的propsthis.memoizedProps = null; // 上一次渲染完成的propsthis.updateQueue = null; // 组件产生的update信息会放在这个队列this.memoizedState = null; // // 上一次渲染完成的statethis.dependencies = null;this.mode = mode; // Effectsthis.flags = NoFlags; // 相当于之前的effectTag, 记录side effect类型this.nextEffect = null; // 单链表结构, 便于快速查找下一个side effectthis.firstEffect = null; // fiber中第一个side effectthis.lastEffect = null; // fiber中最后一个side effectthis.lanes = NoLanes; // 优先级相关this.childLanes = NoLanes; // 优先级相关this.alternate = null; // 对应的是current fiber
}
Fiber工作原理
在弄明白Fiber工作原理之前,我们要先明确一个认知:新的React架构使用了两个Fiber树。
- 一个Fiber树是当前页面dom的抽象,叫
current
; - 另一个Fiber树是在内存中执行更新任务dom的抽象,叫
workInProgress
;
这样做是为了方便比对变化组件,并降低创建的成本,尽可能复用现有代码逻辑,从而提高渲染效率。相关参考视频讲解:进入学习
mount
React代码在第一次执行时,因为页面还没有渲染出来,此时是没有current
树的,只有一个正在构建DOM的workInProgress
树。
假如我们有这样一段代码:
function App() {return (<div><span>牛牛</span><span>不怕困难</span></div>)
}ReactDOM.render(<App/>, document.querySelector('#root'));
基于上面的代码在mount
会生成这样的Fiber树:
可以看到这个图只是在前面的图上增加了fiberRoot
和rootFiber
两个Fiber节点。
- fiberRoot:整个React应用的根节点;
- rootFiber: 某个组件树的根节点;(因为我们可能多次使用
React.render()
函数,这样就会有多个rootFiber)
图中此时fiberRoot对应的rootFiber下面还是空的,因为此时是第一次渲染,页面上没有任何东西,当workInProgress
树构建完成,在mutation
之后,layout
之前,fiberRootd的current
指针会指向workInProgress
树,把它作为新的current
树,此时结构会变成这样:
这时页面渲染完成了,等待下次触发更新时会从
current
树进行拷贝生成workInProgress
树,然后比对更新。
update
如果我们在上面的代码中触发更新,将牛牛
文本改成了勇敢牛牛
,React代码就会开始进行任务调度,因为只有这一个任务,会马上执行,会从current
树的rootFiber进行拷贝生成workInProgress
树的根节点,在经过向下遍历比对,发现相同的就直接从current
树上拷贝复用,直到比对到叶子节点的牛牛
文本变了,这时才会生成新的Fiber(这里只是为了方便解释,其实我这里使用的代码牛牛
不会生成新的Fiber,因为是纯文本,只会替换父级节点的props)
相关文章:

React源码分析(一)Fiber
前言 本次React源码参考版本为17.0.3。 React架构前世今生 查阅文档了解到, React16.x是个分水岭。 React15及之前 在16之前,React架构大致可以分为两层: Reconciler: 主要职责是对比查找更新前后的变化的组件;R…...

小樽 C++指针—— (壹) 指针变量
(壹) 指针变量 一、指针的概念与定义 二、给指针变量p赋值 三、指针变量的的、-运算 四、无类型指针 五、多重指针 C (壹) 指针变量 小明想把从李华家借来的书——《CCF中学生计算机程序设计》还给李华,但李华不在家,于是把书放到书架第3层的最右边…...

java 代码块 万字详解
概述 : 特点 : 格式 : 情景 : 细节 : 演示 : 英文 : //v,新版编辑器无手动添加目录的功能,PC端阅读建议通过侧边栏进行目录跳转;移动端建议用PC端阅读。😂一、概述 :代码块,也称为初始化块,属于类中的成员&…...

杂项-图片隐写
图片隐写的常见隐写方法: 三基色:RGB(Red Green Blue) 图片文件隐写 1.Firework 使用winhex打开文件时会看到文件头部中包含firework的标识,通过firework可以找到隐藏图片。 使用场景:查看隐写的图片文件…...

【高性价比】初学者入门吉他值得推荐购买的民谣单板吉他品牌—VEAZEN费森吉他
“在未知的世界里,我们是一群不疲不倦的行者,执念于真善美,热衷于事物的极致。我们抽丝剥茧,不断地打败自己,超越自己,我们无所畏惧终将成为巨人。”这是VEAZEN吉他官网首页上很明显的一段话,也…...

2023年浙江交安安全员考试题库及答案
百分百题库提供交安安全员考试试题、交安安全员考试真题、交安安全员证考试题库等,提供在线做题刷题,在线模拟考试,助你考试轻松过关。 50.根据《建设工程安全生产管理条例》第65条规定,施工单位有下列()行…...
【新】华为OD机试 - 跳格子(Python)
跳格子 题目 地上共有 N 个格子,你需要跳完地上所有的格子, 但是格子间是有强依赖关系的,跳完前一个格子后, 后续的格子才会被开启,格子间的依赖关系由多组 steps 数组给出, steps[0] 表示前一个格子, steps[1] 表示 steps[0] 可以开启的格子: 比如 [0,1] 表示从跳完第…...
乡村能做社区团购吗?怎么做?我走访调查后发现机会很大
乡村能做社区团购吗?怎么做?我走访调查后发现机会很大#深度触网 #社区团购 #乡村振兴##乡村旅游##县域经济##市场经济##农文旅产业振兴研究院#乡村旅游能带动农产品加工业、服务业、商贸业等相关联产业的发展 乡村能做社区团购吗?怎么做&…...

态路小课堂丨下一代数据中心100G接口第二篇——SFP-DD封装
100G光模块根据封装模式可分为QSFP28、CXP、CFP、CFP2、FCP4、DSFP和SFP-DD等。态路小课堂之前已经大量介绍了相关内容(。 态路小课堂丨下一代数据中心100G接口——DSFP态路小课堂丨100G解决方案-425G NRZ光模块态路小课堂丨什么是100G QSFP28单波光模块?…...
状态栏和导航栏高度获取
/*** 获取导航栏高度*/public static int getNavigationBarHeight(Context context){int navigationBarHeight 0;int resourceId context.getResources().getIdentifier("navigation_bar_height", "dimen", "android")if (resourceId > 0) {…...
插曲:第一桶金 1w 的来由
因为前天跟同事聊天,发现有个比较严重的认知,就是关于赚钱思维。 同事反馈说工作十来年,却没有接过私活,这里话分两头,有可能私 活钱少,但他给我的理由是:私活太麻烦,有时候不敢接&a…...
中国甲基异丁基甲醇行业头部企业市场占有率及排名调研报告
内容摘要 本文调研和分析全球甲基异丁基甲醇发展现状及未来趋势,核心内容如下: (1)全球市场总体规模,分别按销量和按收入进行了统计分析,历史数据2018-2022年,预测数据2023至2029年。 …...

streamlit自定义组件教程和组件开发环境配置
About create your own component: you can follow this tutorial streamlit tutorial 重要!以下步骤都是在教程的基础上更改的。这个教程做的很棒。 Component development environment configuration: 根据文章 https://streamlit-com…...

Windows CMD常用命令
目录 【打开CMD命令】 【网络测试命令】 ipconfig------查看本机网卡信息 ping------测试网络是否通畅 tracert------追踪路由,也可以用来查看网络连通性 telnet------查看目的主机ip的端口号是否开放 tcping------查看目的主机ip的端口号是否开放 【关于路…...

ChIP-seq 分析:数据比对(3)
读取 reads(二者含义相同,下文不做区分)1. ChIPseq reads 比对 在评估读取质量和我们应用的任何读取过滤之后,我们将希望将我们的读取与基因组对齐,以便识别任何基因组位置显示比对读取高于背景的富集。 由于 ChIPseq…...
并非从0开始的c++之旅 day2
并非从0开始的c之旅 day2一、变量1、 变量名的本质二、程序的内存分区模型1、内存分区运行之前运行之后三、栈区注意事项四、堆区1、堆区使用2、堆区注意事项五、全局变量静态变量1、静态变量2、全局变量六、常量1、全局const常量2、局部const常量七、字符串常量一、变量 既能…...

Linux进阶(Shell编程学习一)
由于shell脚本在java项目运维方面极其重要,比如服务的启动脚本,日志的分割脚本,文件的管理脚本大多都是shell脚本去实现的。所以作为java开发者懂linux的基本命令,会基本的shell编程是必要的。 Shell 是一个用 C 语言编写的程序&…...

sql 优化
sql 优化1. mysql 基础架构1.1 mysql 的组成2. mysql 存储引擎2.1MyISAM2.2 InnoDB2.3 MyISAM 和 InnoDB 的对比3. mysql 索引3.1 Hash 索引3.2 B-Tree 索引3.3 BTree 索引3.4 R-Tree 索引3.5 Full-Text 索引4. sql 优化4.1 避免 select *4.2 避免在where子句中使用or来连接条件…...
第7篇:Java的学习路径
目录 1、Java学习主要内容概览 1.1 Java基础 1.2 数据库技术 1.3 动态网页技术 1.4中间件技术...

对抗生成网络GAN系列——Spectral Normalization原理详解及源码解析
🍊作者简介:秃头小苏,致力于用最通俗的语言描述问题 🍊专栏推荐:深度学习网络原理与实战 🍊近期目标:写好专栏的每一篇文章 🍊支持小苏:点赞👍🏼、…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...

css实现圆环展示百分比,根据值动态展示所占比例
代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...

从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...

【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...

ETLCloud可能遇到的问题有哪些?常见坑位解析
数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

在WSL2的Ubuntu镜像中安装Docker
Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包: for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

HDFS分布式存储 zookeeper
hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架,允许使用简单的变成模型跨计算机对大型集群进行分布式处理(1.海量的数据存储 2.海量数据的计算)Hadoop核心组件 hdfs(分布式文件存储系统)&a…...

算法岗面试经验分享-大模型篇
文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer (1)资源 论文&a…...