React原理之Fiber双缓冲

news2024/11/16 3:33:08

前置文章:

  1. React原理之 React 整体架构解读
  2. React原理之整体渲染流程
  3. React原理之Fiber详解

-----读懂这一篇需要对 React 整体架构和渲染流程有大致的概念 😊-----

在前面的文章中,简单介绍了 Fiber 架构,也了解了 Fiber 节点的概念。

Fiber 节点是 Fiber 架构的核心概念之一,它是一种虚拟 DOM 的实现方式。

Fiber 本质上是一个对象, 使用了链表结构

双重缓冲是一种渲染优化技术,其使用两个 Fiber 树来管理渲染,即当前树 current tree工作树 work-in-progress tree。当前树代表屏幕上当前显示的内容,而工作树用于准备下一次的渲染更新,用以实现平滑的更新。

本篇将详细介绍 Fiber 架构的工作原理,即如何使用“双缓存”来完成 Fiber 树的构建与替换

对于 fiber,我们已经有一些了解了。那么 fiber 节点构成的 fiber 树和页面上的 DOM 树有什么关系呢?我们经常看到的 fiber 双缓冲是什么?

双缓冲的概念

双缓冲(Double Buffering)是一种在计算机图形学和用户界面设计中常用的技术,简单来说,就是通过将绘制和显示过程分离,改善图像渲染的流畅性和视觉效果。

在这里插入图片描述

如上图,普通的绘图方式就像是直接在电脑屏幕上画图,用户可以看到绘图的每一个步骤,这样不太优雅。

双缓冲就类似于首先在内存上创建一个“虚拟屏幕”,所有的图形绘制工作都在虚拟屏幕上完成。这个虚拟屏幕就像是一个幕后的画布,绘图或称首先在这个虚拟屏幕上进行,用户看不到绘图的过程。

当虚拟屏幕上的图形绘制完成时,绘图程序会迅速将整个画面一次性拷贝到电脑屏幕上,替换掉之前的画面,这个拷贝过程是瞬间完成的。

这样,用户在屏幕上看到的图像始终都是完整的。

React 中的双缓冲 fiber 树

在 React 源码中,很多方法都需要接收两颗 FiberTree:

function cloneChildFibers(current, workInProgress) {
	// ...
}

current 是当前屏幕上显示内容对应的 FiberNode,workInProgress 指的是正在内存中构建的 FiberNode。

两个 FiberNode 会通过 alternate 属性相互指向:

current.alternate = workInProgress;
workInProgress.alternate = current;

每次状态更新都会产生新的workInProgress Fiber Tree,通过currentworkInProgress的替换,完成DOM更新。

可以从首次渲染(mount)更新(update)这两个阶段来看一下 FiberTree 的构建/替换流程。

首次渲染(mount)

首先我们先了解一下几个概念:

  • fiberRootNode:整个应用的根节点,fiberRootNodecurrent会指向当前页面上已渲染内容对应Fiber树,即current Fiber Tree

  • hostRootFiber: 它是一个具体的 Fiber 节点实例,具有 Fiber 节点的所有属性和方法。通常包含指向宿主环境(如 DOM)的引用,并且负责协调 React 组件与宿主环境之间的交互。

  • rootFiber:一个通用术语,用来指代 Fiber 树的根节点,包括HostRootFiber,其他类型的根 Fiber 等。

  • workInProgress Fiber Tree: 内存中构建的树,简写 WIP FiberTree。

  • current Fiber Tree: 页面显示的树。

// 示例
function App() {
	const [num, setNum] = useState(0);
	return <p onClick={() => setNum((prevNum) => prevNum + 1)}>{num}</p>;
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
流程一:

当执行 ReactDOM.createRoot 时:

// ReactFiberRoot.js 伪代码
function createFiberRoot() {
	//...

	// 创建 FiberRootNode 实例
	const root = new FiberRootNode(/* 参数 */);
	// 创建 HostRootFiber 实例
	const uninitializedFiber = createHostRootFiber(/* 参数 */);
	// 将 HostRootFiber 设置为 FiberRoot 的 current 属性
	root.current = uninitializedFiber;

	// ...
	return root;
}

此时会创建 fiberRootNode 和 hostRootFiber,fiberRootNode 通过 current 来指向 hostRootFiber。

即创建如下的结构:

在这里插入图片描述

由于是首屏渲染,页面中还没有挂载任何DOM,所以fiberRootNode.current指向的rootFiber没有任何子Fiber节点(即 current Fiber Tree 为空)。

流程二 (render)

接下来进入render阶段,根据组件返回的 JSX 在内存中以深度优先原则依次创建wip FiberNode并连接在一起构建 Fiber 树,即workInProgress Fiber Tree

在这里插入图片描述

生成的 wip FiberTree 里面的每一个 FiberNode 会和 current FiberTree 里面的 FiberNode 通过alternate进行关联。但是目前 currentFiberTree 里面只有一个 HostRootFiber,因此就只有这个 HostRootFiber 进行了 alternate 的关联。

流程三 (commit)

当 wip FiberTree 生成完毕后,进入 commit 阶段,此时 FiberRootNode 就会被传递给 Renderer(渲染器),接下来就是进行渲染工作。已构建完的workInProgress Fiber Tree在此阶段渲染到页面。

渲染工作完毕后,浏览器中就显示了对应的 UI,此时 FiberRootNode.current 就会指向这颗 wip Fiber Tree,曾经的 wip Fiber Tree 它就会变成 current FiberTree,完成了双缓存的工作:

在这里插入图片描述

更新(update)

点击p节点触发状态改变而更新,这样就进入了 update。

流程四 (render)

update 会开启一次新的render阶段并构建一棵新的workInProgress Fiber Tree,流程和前面一样。

新的 wip Fiber Tree 里面的每一个 FiberNode 和 current Fiber Tree 的每一个 FiberNode 通过 alternate 属性进行关联。

在这里插入图片描述

流程五 (commit)

当 wip Fiber Tree 生成完毕后, workInProgress Fiber Tree就完成了render阶段的构建,进入commit阶段渲染到页面上。

在这里插入图片描述

FiberRootNode 会被传递给 Renderer 进行渲染,此时宿主环境所渲染出来的真实 UI 对应的就是左边 Fiber Tree (此时还是 wip Fiber Tree) 对应的 DOM 结构,FiberRootNode.current 就会指向左边这棵树,右边的树就再次成为了新的 wip Fiber Tree。

以上两棵 fiber 树交替并更新 DOM 的过程这就是 fiber 双缓冲的原理。

扩展

在构建 workInProgress Fiber Tree 时会尝试复用 current Fiber Tree 中对应的 FiberNode 的数据,这个决定是否复用的过程就是 Diff 算法。留个位置放以后讲 Diff 算法的 🔗~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2058578.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python功能强大且易于使用的命令行 shell库之xonsh使用详解

概要 Xonsh 是一种基于 Python 的跨平台、用户友好的命令行 shell。它结合了 Python 和传统 shell 命令的优势&#xff0c;允许用户在同一个环境中使用两者。Xonsh 为开发者和系统管理员提供了强大的工具&#xff0c;简化了任务自动化和脚本编写。本文将详细介绍 xonsh 库&…

基于php网上差旅费报销系统设计与实现

网上报销系统以LAMP(LinuxApacheMySQLPHP)作为平台,涉及到PHP语言、MySQL数据库、JavaScript语言、HTML语言。 2.1 PHP语言简介 PHP&#xff0c;一个嵌套的缩写名称&#xff0c;是英文 “超级文本预处理语言”&#xff08;PHP: Hypertext Preprocessor&#xff09;的缩写。P…

又学了几个新的comfyui小技巧,分享给大家!

前言 掌握一些小技巧&#xff0c;提升效率&#xff01; 1、图像选择器 出图批次是四张&#xff0c;然后想选一张图进入到之后的工作流&#xff0c;就可以用这个节点 默认是这样的 运行到这个节点的时候&#xff0c;会出现四张图片&#xff0c;选中满意的图片&#xff0c;点…

RM惯性测量单元IMU

在Robomaster比赛中&#xff0c;一般各大参赛队会在机器人的云台上搭载IMU&#xff0c;用以反馈云台的yaw轴和pitch轴的角度和角速度。 需要注意的是&#xff0c;尽管依靠云台电机6020的编码器同样可以实现以上数据的获取&#xff0c;但是由于云台控制对于灵敏度和精度的要求比…

微信删除的聊天记录怎么恢复?实测有效,3招教您轻松恢复

微信已成为我们传递信息、分享情感的重要桥梁。然而&#xff0c;不小心误删的聊天记录往往让人懊悔不已&#xff0c;尤其是那些珍贵的对话和重要的信息。面对微信删除的聊天记录怎么恢复的问题&#xff0c;很多人都会感到束手无策。 但别担心&#xff0c;无论您是技术小白还是…

单因子年化23.7%,基于deap的因子挖掘,我改进了fitness和metrics方案(附python代码和数据)

原创文章第626篇&#xff0c;专注“AI量化投资、世界运行的规律、个人成长与财富自由"。 我们目前投入使用的因子挖掘&#xff0c;基于两个框架&#xff0c;deap和gplearn&#xff0c;deap做一点点改动&#xff0c;就可以完美应用于多标的截面因子挖掘。而gplearn如果要支…

秋叶SD整合安装包更新了!8月最新版4.9【附下载】

01 SD整合包可以扫描下方&#xff0c;免费获取 02 安装步骤 下载好后解压双击打开即可使用&#xff08;第一次安装部署时间稍长&#xff0c;等待一会即可&#xff09; 安装完进入界面后&#xff0c;点击右下角一键启动&#xff0c;稍微等待一会儿就会加载WebUI。 选择大模…

期货模拟交易系统考核选拔系统资管分仓有哪些特点?

分仓账户本身是为了风险管理和资金管理的目的而设立的&#xff0c;‌通过将资金分散到不同的账户中&#xff0c;‌可以降低整体风险&#xff0c;‌避免某个合约的亏损对整个资金造成过大的影响。‌这种分散投资的策略有助于提高交易的安全性。‌然而&#xff0c;‌分仓账户的安…

MySQL 索引合并优化实践

在生产环境的数据库中&#xff0c;经常会看到有些 SQL 的 where 条件包含&#xff1a;普通索引等值 主键范围查询 order by limit。明明走普通索引效率更高&#xff0c;但是选择走了索引合并&#xff0c;本文就对这种索引合并的情况研究一下。 作者&#xff1a;张洛丹&#x…

细数目标管理的坑:避免陷阱,实现高效执行

目标管理作为一种被广泛采用的管理方法&#xff0c;通过明确的目标设定和追踪&#xff0c;提升组织绩效和员工动力。然而&#xff0c;正如任何管理工具一样&#xff0c;目标管理也并非完美无缺&#xff0c;其在实际应用中往往伴随着一系列潜在的“坑”。 一、目标设定&#x…

如何使用DataGear零编码快速制作MQTT物联网实时数据看板

DataGear是一个开源免费的数据可视化分析平台&#xff0c;企业版在开源版基础上开发&#xff0c;新增了诸多企业级特性&#xff0c;包括&#xff1a;MySQL及更多部署数据库支持、MQTT/WebSocket/Redis/MongoDB数据集、OAuth2.0/CAS/JWT/LDAP统一登录支持、前后端敏感信息加密传…

ArcGIS 数据服务在三维 Cesium/SuperMap 项目中使用遇到的一些问题及其解决方法

ArcGIS 数据服务在三维 Cesium/SuperMap 项目中使用遇到的一些问题及其解决方法 一、三维系统支持的 ArcGIS 服务及其投影 1、动态服务 ArcGIS 动态服务的数据&#xff0c;支持任意投影在三维系统中加载。 2、切片服务 ArcGIS 切片服务仅支持 3857(web 墨卡托投影)&#x…

C++ 设计模式(1. 单例模式)

单例模式是一种创建型设计模式&#xff0c; 它的核心思想是保证一个类只有一个实例&#xff0c;并提供一个全局访问点来访问这个实例。 特点 全局访问点的意思是&#xff0c;为了让其他类能够获取到这个唯一实例&#xff0c;该类提供了一个全局访问点&#xff08;通常是一个静态…

锐特驱动器ECR系列IO输出高电平配置

设置极性&#xff1a;常闭值0 默认输出极性常开&#xff0c;平时高组态或无电平输出&#xff0c;点通工作时输出低电平&#xff1b;常闭平时低电平&#xff0c;工作时输出高电平&#xff1b; 常开常闭概念具体可参考&#xff1a; http://t.csdnimg.cn/TIsW9 设置输出功能&…

如何用Java SpringBoot+Vue搭建校内跑腿业务系统?实战教程解析

✍✍计算机毕业编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java、…

​​​​​​​STM32通过SPI硬件读写W25Q64

目录 STM32通过SPI硬件读写W25Q64 1. STM32的SPI外设简介 2. STM32的SPI框图 2.1 数据寄存器和移位寄存器&#xff08;左上角部分&#xff09; 控制逻辑&#xff08;其余右下角的部分&#xff09; 3.STM32的SPI基本框图 4. STM32的SPI主模式全双工连续传输 时序图 5. S…

网安新声 | 从微软“狂躁许可”漏洞事件看安全新挑战与应对策略

网安加社区【网安新声】栏目&#xff0c;汇聚网络安全领域的权威专家与资深学者&#xff0c;紧跟当下热点安全事件、剖析前沿技术动态及政策导向&#xff0c;以专业视野和前瞻洞察&#xff0c;引领行业共同探讨并应对新挑战的策略与可行路径。 近期&#xff0c;微软披露了一个最…

AIGC企业知识库系统的全方位应用

在知识爆炸的时代&#xff0c;企业如同航行在浩瀚信息海洋中的巨轮&#xff0c;每一滴知识的浪花都可能成为推动其破浪前行的动力。而 AIGC企业知识库系统可以帮助企业精准捕捞、高效利用这些宝贵资源&#xff0c;不仅重塑了企业知识管理的版图&#xff0c;更引领了一场前所未有…

秋招力扣Hot100刷题总结——回溯

回溯问题通常应用于解决排列组合等问题&#xff0c;需要注意的是回溯函数中的参数、结束条件、遍历开始顺序等。 回溯三部曲&#xff1a; &#xff08;1&#xff09;确定递归函数的参数。 &#xff08;2&#xff09;确定递归函数的终止条件。 &#xff08;3&#xff09;确定单层…

错误:Input string was not in a correct format.

之前写的桌面端&#xff0c;在国内客户电脑运行着没问题&#xff0c;到欧洲国家电脑上就挂掉了 原因&#xff1a;TM 小数点不是. 而是, 是逗号&#xff0c;不明觉厉 解决办法&#xff1a; 1、更改客户电脑配置 这里把逗号改成.就行了 但是这种办法比较笨&#xff0c;总不能…