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最终都有输出,输出仅由宿主组件在叶子节点创建
输出随后沿树向上传输
最终所有的输出内容都会提供给渲染器,渲染器将其刷新到渲染环境中
渲染器负责定义如何创建和更新输出

浙公网安备 33010602011771号