React基础理论概念、VirtualDOM、Fiber等的笔记

参考:

  1. https://github.com/reactjs/react-basic
  2. https://github.com/acdlite/react-fiber-architecture

React 基本理论概念

React核心前提:UI将数据投影到另一种形式的数据中,相同的输入产生相同的输入

function NameBox(name) {
return {
fontWeight: 'bold',
labelContent: name
}
}
'Sebastian Markbåge' ->
{ fontWeight: 'bold', labelContent: 'Sebastian Markbåge' };

抽象

UI可抽象为可重复使用的部分,而不会泄漏实现细节,eg:从另一个函数调用另一个函数

function FancyUserBox(user) {
return {
borderStyle: '1px solid blue',
childContent: [
'Name: ',
NameBox(user.firstName + ' ' + user.lastName)
}
}
{ firstName: 'Sebastian', lastName: 'Markbåge' } ->
{
borderStyle: '1px solid blue',
childContent: [
'Name: ',
{ fontWeight: 'bold', labelContent: 'Sebastian Markbåge' }
]
};

进一步抽象组合:将两个或多个不同的抽象组合成一个新的抽象

function FancyBox(children) {
return {
borderStyle: '1px solid blue',
children: children
};
}
function UserBox(user) {
return FancyBox([
'Name: ',
NameBox(user.firstName + ' ' + user.lastName)
]);
}

状态

UI不仅是业务逻辑状态的复制

function FancyNameBox(user, likes, onClick) {
return FancyBox([
'Name: ', NameBox(user.firstName + ' ' + user.lastName),
'Likes: ', LikeBox(likes),
LikeButton(onClick)
]);
}
// Implementation Details
var likes = 0;
function addOneMoreLike() {
likes++;
rerender();
}
// Init
FancyNameBox(
{ firstName: 'Sebastian', lastName: 'Markbåge' },
likes,
addOneMoreLike
);

使用副作用更新状态,在更新过程中返回下一个版本的状态

记忆化

如果我们知道该函数是纯函数,那么反复调用同一个函数就是一种浪费。我们可以创建一个函数的记忆版本,以跟踪最后一个参数和最后一个结果。这样,如果我们继续使用相同的值,就不必重新执行它。

function memoize(fn) {
var cachedArg;
var cachedResult;
return function(arg) {
if (cachedArg === arg) {
return cachedResult;
}
cachedArg = arg;
cachedResult = fn(arg);
return cachedResult;
};
}
var MemoizedNameBox = memoize(NameBox);
function NameAndAgeBox(user, currentTime) {
return FancyBox([
'Name: ',
MemoizedNameBox(user.firstName + ' ' + user.lastName),
'Age in milliseconds: ',
currentTime - user.dateOfBirth
]);
}

什么是Virtual DOM

虚拟DOM也是一种编程理念,UI以JS对象表达并存储于内存中,通过ReactDOM等类库与真实DOM同步

Shadow DOM和Virtual DOM的区别

Shadow DOM是浏览器技术,主要用于在Web组件中封装变量和CSS
Virtual DOM是JS类库基于浏览器API实现的概念

什么是React Fiber?

React Fiber的核心作用:实现虚拟DOM可异步可中断增量式更新

主要功能:【增量渲染】:具体将渲染工作拆分成多个块并将其分散到多个帧上。

什么是调和 Reconciliation?

Reconciliation:React使用算法来比较一个树与另一颗树的差异来确定哪些部分需要更改
Update:用于渲染React应用的数据发生变化,eg:调用setState导致重新渲染你

React API核心思想:将更新视为导致整个应用重新渲染

调和 =》 虚拟DOM背后的算法

渲染React应用程序时,会生成一个描述App的节点树将其保存到内存中
之后,该树被刷新到渲染环境,在浏览器应用程序中会转换为一组DOM操作

当应用程序更新时(eg: setState)会生成一颗新的树,新树和旧树进行差异化,以计算更新渲染的应用程序所需操作

React设计 =》 调和和渲染分开

  • 调和器负责计算树的哪些部分发生变化
  • 渲染器使用该信息来实际更新渲染的应用程序

这种分离意味着 React DOM 和 React Native 可以使用自己的渲染器,同时共享 React 核心提供的同一个协调器。

Fiber 重新实现了调和器。它主要不关心渲染,尽管渲染器需要进行更改才能支持(并利用)新架构。

什么是Fiber?

Fiber的目标:使得React能够利用调度

  • 暂停工作,稍后继续
  • 对不同类型的工作分配优先级别
  • 重复使用以前完成的工作
  • 如果不再需要则中止工作

首先需要一种方法将工作分解为单元。从某种意义上说,这就是 Fiber。Fiber 代表工作单元。
React组件作为数据函数的概念

v = f(d)

渲染React应用 =》类似于调用一个函数,该函数的主体包含对其他函数的调用

eg: 计算机通过调用堆栈来跟踪程序的执行情况,执行函数时,会将新的堆栈框架添加到堆栈中
该堆栈框架代表该函数执行的工作

在处理UI时,若一次性处理过多工作会导致 动画丢帧不连贯

组件比函数具有更多具体的关注点

解决该问题的API: requestIdleCallback => 安排在空闲期间调用低优先级函数
requeestAnimationFrame安排在下一个动画帧调用高优先级函数

将渲染工作分解为增量单元 | Fiber: 可以随意中断调用堆栈并手动操作堆栈帧

React Fiber的目的:Fiber是堆栈的重新实现,专门用于React组件,单个fiber视为虚拟堆栈框架

将堆栈框架保存在内存中,需要的时候执行
除了调度之外,手动处理堆栈帧 还可以释放并发和错误边界等功能

Fiber的结构

Fiber是一个JS对象,包含组件和其输入输出的信息

一个Fiber对应一个堆栈框架,也对应一个组件的一个实例

Fiber是如何工作的? https://www.facebook.com/groups/2003630259862046/permalink/2054053404819731/

Fiber的关键字段

type和key

Fiber的type和key的作用 和 React元素的作用相同
当从Element创建Fiber时,type和key会直接复制

Fiber的type: 描述对应的组件
对于复合组件,类型是函数或类组件本身
对于宿主组件(div、span)等,类型是字符串
key和type在协调期间可用于确定Fiber是否可以重复使用

child和sibling

child =》 指向子Fiber

eg:
function Parent() {
return <Child/>
}

sibling =》指向兄弟Fiber

function Parent() {
return [<Child1/>, <Child2/>]
}

子Fiber形成一个单链表,头部是第一个子Fiber

return

返回Fiber是程序在处理完当前Fiber后返回到的Fiber
在概念上和堆栈帧的返回地址相同 =》可认为是父Fiber

pendingProps和memoizedProps

props是函数的参数
fiber的参数pendingProps在执行开始时设置
memoizedProps在执行结束时设置
当输入pendingProps等于memoizedProps,表明当前Fiber之前的输出可重复使用

pendingWorkPriority

表明该Fiber代表的工作的优先级的数字。
ReactPriorityLevel模块列出不同的优先级和代表的含义
数字越大优先级越低

function matchesPriority(fiber, priority) {
return fiber.pendingWorkPriority !== 0 &&
fiber.pendingWorkPriority <= priority
}

调度程序使用优先级字段来搜索下一个要执行的工作单元

在任何时候,一个组件实例最多存在两个与之对应的Fiber

  • 当前已刷新的Fiber
  • 正在进行中的Fiber(内存中的替代品

cloneFiber会尝试重用Fiber,最大限度减少分配

每个Fiber最终都有输出,输出仅由宿主组件在叶子节点创建
输出随后沿树向上传输

最终所有的输出内容都会提供给渲染器,渲染器将其刷新到渲染环境中
渲染器负责定义如何创建和更新输出

posted @   Felix_Openmind  阅读(13)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
*{cursor: url(https://files-cdn.cnblogs.com/files/morango/fish-cursor.ico),auto;}
点击右上角即可分享
微信分享提示