网站制作哪个好薇/谷歌浏览器免费入口
这是我的剖析 React 源码的第二篇文章,如果你没有阅读过之前的文章,请务必先阅读一下 第一篇文章 中提到的一些注意事项,能帮助你更好地阅读源码。
文章相关资料
- React 16.8.6 源码中文注释,这个链接是文章的核心,文中的具体代码及代码行数都是依托于这个仓库
- 热身篇
- render 流程(二)
现在请大家打开 我的代码 并定位到 react-dom 文件夹下的 src 中的 ReactDOM.js 文件,今天的内容会从这里开始。
render
想必大家在写 React 项目的时候都写过类似的代码
ReactDOM.render(<APP />, document.getElementById('root')
这句代码告诉了 React 应用我们想在容器中渲染出一个组件,这通常也是一个 React 应用的入口代码,接下来我们就来梳理整个 render
的流程,并且会分为几篇文章来讲解,因为流程实在太长了。
首先请大家先定位到 ReactDOM.js 文件的第 702 行代码,开始今天的旅程。
这部分代码其实没啥好说的,唯一需要注意的是在调用 legacyRenderSubtreeIntoContainer
函数时写死了第四个参数 forceHydrate
为 false
。这个参数为 true
时表明了是服务端渲染,因为我们分析的是客户端渲染,因此后面有关这部分的内容也不会再展开。
接下来进入 legacyRenderSubtreeIntoContainer
函数中,这部分代码分为两块来讲。第一部分是没有 root
之前我们首先需要创建一个 root
(对应这篇文章),第二部分是有 root
之后的渲染流程(对应接下来的文章)。
一开始进来函数的时候肯定是没有 root
的,因此我们需要去创建一个 root
,大家可以发现这个 root
对象同样也被挂载在了 container._reactRootContainer
上,也就是我们的 DOM 容器上。
如果你手边有 React 项目的话,在控制台键入如下代码就可以看到这个 root
对象了。
document.querySelector('#root')._reactRootContainer
大家可以看到 root
是 ReactRoot
构造函数构造出来的,并且内部有一个 _internalRoot
对象,这个对象是本文接下来要重点介绍的 fiber
对象,接下来我们就来一窥究竟吧。
首先还是和上文中提到的 forceHydrate
属性相关的内容,不需要管这部分,反正 shouldHydrate
肯定为 false
。
接下来是将容器内部的节点全部移除,一般来说我们都是这样写一个容器的的
<div id='root'></div>
这样的形式肯定就不需要去移除子节点了,这也侧面说明了一点那就是容器内部不要含有任何的子节点。一是肯定会被移除掉,二来还要进行 DOM 操作,可能还会涉及到重绘回流等等。
最后就是创建了一个 ReactRoot
对象并返回。接下来的内容中我们会看到好几个 root
,可能会有点绕。
在 ReactRoot
构造函数内部就进行了一步操作,那就是创建了一个 FiberRoot
对象,并挂载到了 _internalRoot
上。和 DOM 树一样,fiber
也会构建出一个树结构(每个 DOM 节点一定对应着一个 fiber
对象),FiberRoot
就是整个 fiber
树的根节点,接下来的内容里我们将学习到关于 fiber
相关的内容。这里提及一点,fiber
和 Fiber 是两个不一样的东西,前者代表着数据结构,后者代表着新的架构。
在 createFiberRoot
函数内部,分别创建了两个 root
,一个 root
叫做 FiberRoot
,另一个 root
叫做 RootFiber
,并且它们两者还是相互引用的。
这两个对象内部拥有着数十个属性,现在我们没有必要一一去了解它们各自有什么用处,在当下只需要了解少部分属性即可,其他的属性我们会在以后的文章中了解到它们的用处。
对于 FiberRoot
对象来说,我们现在只需要了解两个属性,分别是 containerInfo
及 current
。前者代表着容器信息,也就是我们的 document.querySelector('#root')
;后者指向 RootFiber
。
对于 RootFiber
对象来说,我们需要了解的属性稍微多点
function FiberNode(tag: WorkTag,pendingProps: mixed,key: null | string,mode: TypeOfMode,
) {this.stateNode = null;this.return = null;this.child = null;this.sibling = null;this.effectTag = NoEffect;this.alternate = null;
}
stateNode
上文中已经讲过了,这里就不再赘述。
return
、child
、sibling
这三个属性很重要,它们是构成 fiber
树的主体数据结构。fiber
树其实是一个单链表树结构,return
及 child
分别对应着树的父子节点,并且父节点只有一个 child
指向它的第一个子节点,即便是父节点有好多个子节点。那么多个子节点如何连接起来呢?答案是 sibling
,每个子节点都有一个 sibling
属性指向着下一个子节点,都有一个 return
属性指向着父节点。这么说可能有点绕,我们通过图来了解一下这个 fiber
树的结构。
const APP = () => (<div><span></span><span></span></div>
)
ReactDom.render(<APP/>, document.querySelector('#root'))
假如说我们需要渲染出以上组件,那么它们对应的 fiber
树应该长这样
从图中我们可以看到,每个组件或者 DOM 节点都会对应着一个 fiber
对象。另外你手边有 React 项目的话,也可以在控制台输入如下代码,查看 fiber
树的整个结构。
// 对应着 FiberRoot
const fiber = document.querySelector('#root')._reactRootContainer._internalRoot
另外两个属性在本文中虽然用不上,但是看源码的时候笔者觉得很有意思,就打算拿出来说一下。
在说 effectTag
之前,我们先来了解下啥是 effect
,简单来说就是 DOM 的一些操作,比如增删改,那么 effectTag
就是来记录所有的 effect 的,但是这个记录是通过位运算来实现的,这里 是 effectTag
相关的二进制内容。
如果我们想新增一个 effect
的话,可以这样写 effectTag |= Update
;如果我们想删除一个 effect
的话,可以这样写 effectTag &= ~Update
。
最后是 alternate
属性。其实在一个 React 应用中,通常来说都有两个 fiebr
树,一个叫做 old tree,另一个叫做 workInProgress tree。前者对应着已经渲染好的 DOM 树,后者是正在执行更新中的 fiber tree,还能便于中断后恢复。两棵树的节点互相引用,便于共享一些内部的属性,减少内存的开销。毕竟前文说过每个组件或 DOM 都会对应着一个 fiber
对象,应用很大的话组成的 fiber
树也会很大,如果两棵树都是各自把一些相同的属性创建一遍的话,会损失不少的内存空间及性能。
当更新结束以后,workInProgress tree 会将 old tree 替换掉,这种做法称之为 double buffering,这也是性能优化里的一种做法,有兴趣的同学可以自行查找资料。
相关参考视频讲解:进入学习
总结
以上就是本文的全部内容了,最后通过一张流程图总结一下这篇文章的内容。
最后
阅读源码是一个很枯燥的过程,但是收益也是巨大的。如果你在阅读的过程中有任何的问题,都欢迎你在评论区与我交流。
另外写这系列是个很耗时的工程,需要维护代码注释,还得把文章写得尽量让读者看懂,最后还得配上画图,如果你觉得文章看着还行,就请不要吝啬你的点赞。
下一篇文章还是 render 流程相关的内容。
相关文章:

React源码分析8-状态更新的优先级机制
这是我的剖析 React 源码的第二篇文章,如果你没有阅读过之前的文章,请务必先阅读一下 第一篇文章 中提到的一些注意事项,能帮助你更好地阅读源码。 文章相关资料 React 16.8.6 源码中文注释,这个链接是文章的核心,文…...

如何在ChatGPT的API中支持多轮对话
一、问题 ChatGPT的API支持多轮对话。可以使用API将用户的输入发送到ChatGPT模型中,然后将模型生成的响应返回给用户,从而实现多轮对话。可以在每个轮次中保留用户之前的输入和模型生成的响应,以便将其传递给下一轮对话。这种方式可以实现更…...

华为OD机试模拟题 用 C++ 实现 - 猜字谜(2023.Q1)
最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 最多获得的短信条数(2023.Q1)) 文章目录 最近更新的博客使用说明猜字谜题目输入输出描述备注示例一输入输出示例二输入输出思路Code使用说明 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,...

Containerd容器运行时将会替换Docker?
文章目录一、什么是Containerd?二、Containerd有哪些功能?三、Containerd与Docker的区别四、Containerd是否会替换Docker?五、Containerd安装、部署和使用公众号: MCNU云原生,欢迎微信搜索关注,更多干货&am…...

java虚拟机中对象创建过程
java虚拟机中对象创建过程 我们平常创建一个对象,仅仅只是使用new关键字new一个对象,这样一个对象就被创建了,但是在我们使用new关键字创建对象的时候,在java虚拟机中一个对象是如何从无到有被创建的呢,我们接下来就来…...

3485. 最大异或和
Powered by:NEFU AB-IN Link 文章目录3485. 最大异或和题意思路代码3485. 最大异或和 题意 给定一个非负整数数列 a,初始长度为 N。 请在所有长度不超过 M的连续子数组中,找出子数组异或和的最大值。 子数组的异或和即为子数组中所有元素按位异或得到的…...

SpringBoot:SpringBoot配置文件.properties、.yml 和 .ymal(2)
SpringBoot配置文件1. 配置文件格式1.1 application.properties配置文件1.2 application.yml配置文件1.3 application.yaml配置文件1.4 三种配置文件优先级和区别2. yaml格式2.1 语法规则2.2 yaml书写2.2.1 字面量:单个的、不可拆分的值2.2.2 数组:一组按…...

QT 学习之QPA
QT 为实现支持多平台,实现如下类虚函数 Class Overview QPlatformIntegration QAbstractEventDispatcherQPlatformAccessibilityQPlatformBackingStoreQPlatformClipboardQPlatformCursorQPlatformDragQPlatformFontDatabaseQPlatformGraphicsBufferQPlatformInput…...

Pytorch中FLOPs和Params计算
文章目录一. 含义二. 使用thop库计算FLOPs和Params三. 注意四. 相关链接一. 含义 FLOPs(计算量):注意s小写,是floating point operations的缩写(这里的小s则表示复数),表示浮点运算数ÿ…...

DP1621国产LCD驱动芯片兼容替代HT1621B
目录DP1621简介DP1621芯片特性DP1621简介 DP1621是点阵式存储映射的LCD驱动器芯片,可支持最大128点(32SEG * 4COM)的 LCD屏,也支持2COM和3COM的LCD屏。单片机可通过3/4个通信脚配置显示参数和发送显示数据,也可通过指…...

Linux 用户管理
用户管理 useradd新增用户 格式:useradd [参数] 用户名称 常用参数: -c comment 指定一段注释性描述。 -d 目录 指定用户主目录,如果此目录不存在,则同时使用-m选项,可以创建主目录。 -g 用户组 指定用户所属的用户组…...

前端vue面试题(持续更新中)
vue-router中如何保护路由 分析 路由保护在应用开发过程中非常重要,几乎每个应用都要做各种路由权限管理,因此相当考察使用者基本功。 体验 全局守卫: const router createRouter({ ... }) router.beforeEach((to, from) > {// .…...

Java查漏补缺-从入门到精通汇总
Java查漏补缺(01)计算机的硬件与软件、软件相关介绍、计算机编程语言、Java语言概述、Java开发环境搭建、Java开发工具、注释、API文档、JVM Java查漏补缺(02)关键字、标识符、变量、基本数据类型介绍、基本数据类型变量间运算规…...

软件测试2年半的我,谈谈自己的理解...
软件测试两年半的我,谈谈自己的理解从2020年7月毕业,就成为一名测试仔。日子混了一鲲年,感觉需要好好梳理一下自己的职业道路了,回顾与总结下吧。一、测试的定位做事嘛,搞清楚自己的定位很重要。要搞清楚自己的定位&am…...

什么是SAS硬盘
什么是SAS硬盘SAS是新一代的SCSI技术,和Serial ATA(SATA)硬盘都是采用串行技术,以获得更高的传输速度,并通过缩短连结线改善内部空间等。SAS是并行SCSI接口之后开发出的全新接口。此接口的设计是为了改善存储系统的效能、可用性和扩充性&…...

一文理解服务端渲染SSR的原理,附实战基于vite和webpack打造React和Vue的SSR开发环境
SSR和CSR 首先,我们先要了解什么是SSR和CSR,SSR是服务端渲染,CSR是客户端渲染,服务端渲染是指 HTTP 服务器直接根据用户的请求,获取数据,生成完整的 HTML 页面返回给客户端(浏览器)展…...

Matlab 实用小函数汇总
文章目录Part.I 元胞相关Chap.I 创建空 char 型元胞Part.II 矩阵相关Chap.I 矩阵插入元素Part.III 字符串相关Chap.I 获取一个文件夹下所有文件的文件名的部分内容Part.IV 结构体相关Chap.I 读取结构体Chap.II 取结构体中某一字段的所有值本篇博文记录一些笔者使用 Matlab 时&a…...

Echarts 仪表盘倾斜一定角度显示,非中间对称
第024个点击查看专栏目录大多数的情况下,制作的仪表盘都是中规中矩,横向中间对称,但是生活中的汽车,摩托车等仪表盘确是要倾斜一定角度的,Echarts中我们就模拟一个带有倾斜角度的仪表盘。核心代码见示例源代码 文章目录…...

Vue中如何利用websocket实现实时通讯
首先我们可以先做一个简单的例子来学习一下简单的websocket模拟聊天对话的功能 原理很简单,有点像VUE中的EventBus,用emit和on传来传去 首先我们可以先去自己去用node搭建一个本地服务器 步骤如下 1.新建一个app.js,然后创建pagejson.js文…...

力扣解法汇总1144. 递减元素使数组呈锯齿状
目录链接: 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目: https://github.com/September26/java-algorithms 原题链接:力扣 描述: 给你一个整数数组 nums,每次 操作 会从中选择一个元素并 将该元素的…...

Spring彻头彻尾的讲解,按照Spring框架启动流程,逐步剖析问题,不再是大杂烩!
文章目录1. 定义Spring Bean篇1.1 定义Spring Bean的几种方式1.1.1 XML文件定义Spring Bean1.1.2 JavaConfig定义Spring Bean1.1.3 Component注解定义SpringBean1.2 装配Spring Bean的四种常用方式1.2.1 手动装配 XML文件1.2.2 自动装配 XML文件1.2.3 手动装配 JavaConfig文…...

[2]MyBatis+Spring+SpringMVC+SSM整合一套通关
二、Spring 1、Spring简介 1.1、Spring概述 官网地址:https://spring.io/ Spring 是最受欢迎的企业级 Java 应用程序开发框架,数以百万的来自世界各地的开发人员使用 Spring 框架来创建性能好、易于测试、可重用的代码。 Spring 框架是一个开源的 Jav…...

Javascript的API基本内容(三)
一、事件流 假设页面里有个div,当触发事件时,会经历两个阶段,分别是捕获阶段、冒泡阶段简单来说:捕获阶段是 从父到子 冒泡阶段是从子到父实际工作都是使用事件冒泡为主 二、页面加载事件 加载外部资源(如图片、外联CS…...

【Python入门第十九天】Python 函数
函数是一种仅在调用时运行的代码块。 可以将数据(称为参数)传递到函数中。 函数可以把数据作为结果返回。 创建函数 在 Python 中,使用 def 关键字定义函数: 实例 def my_function():print("Hello from a function&quo…...

web前端性能优化
3.性能检测 当面对具体的项目实践时,该如何快速提升性能体验呢?或者说如何能够准确地定位到性能瓶颈呢?难道要比对着优化知识点清单,一项一项手动排查或完全凭借经验去处理吗?不,我们需要有一整套清晰科学…...

Telnet 基础实验2: SSH 实验
Telnet 基础实验2: SSH 实验 本实验只能使用 eNSP中 AR 系统的路由器做 拓扑图 SSH : Secure Shell 是一个网络安全协议,基本于 TCP 协议 22 端口传输数据,通过对网络数据的加密,使其能够在一个不安全的网络环境中&a…...

Panda Farm:首个部署在 Arbitrum 上的轻量化 GameFi 游戏
在2月16日,Bitget平台宣布 Launchpad 重新启动,并推出了重启后的首个项目 Panda Farm(BBO),该 Launchpad 启动后得到了较高的关注。 Panda Farm 是部署在 Arbitrum 上的 GameFi应用,这可能首先意味着 Bitge…...

Redis实现分布式锁
1、使用背景几乎每个互联网公司中都使用了分布式部署,分布式服务下,就会遇到对同一个资源的并发访问的技术难题,如秒杀、下单减库存等场景。这些场景有一个共同特点就是访问量激增,虽然在系统设计时会通过限流、异步、排队等方式优…...

刷题小抄1-2数之和
时间复杂度和空间复杂度 对于一个算法高效性的评估,分为时间复杂度与空间复杂度两种,在算法优化到极致的情况下,只能舍弃时间来换取空间,或者舍弃空间来换取时间,故而两者可以说是互斥关系 时间复杂度衡量的是算法运行的速度,而空间复杂度衡量的是算法运行所需要的额外内存空…...

axicom的测试文档
目录)SQLpython开放性业务题(二选一)完整代码SQL 问题描述 SQL, 请根据前一周各产品的总GMV将其分成五类:GMV Top 20%、20%-40%,40%-60%,60%-80%以及Bottom 20%的产品组,请计算这五…...