React基础理论概念、VirtualDOM、Fiber等的笔记
参考:
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最终都有输出,输出仅由宿主组件在叶子节点创建
输出随后沿树向上传输
最终所有的输出内容都会提供给渲染器,渲染器将其刷新到渲染环境中
渲染器负责定义如何创建和更新输出
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具