React Fiber 节点的主要属性及其用途
#React
目录
总结
- 再读一遍
- todo
1. 篇一
1.1. 节点标识和类型相关
interface FiberNode {
// 标记 Fiber 节点的类型
tag: WorkTag; // 例如:FunctionComponent = 0, ClassComponent = 1, HostComponent = 5 等
// 元素的唯一标识
key: null | string;
// 元素的类型,对应 React Element 的 type
// 可能是函数、类或原生 DOM 类型(如 'div')
elementType: any;
// 实际使用的类型,考虑了 elementType 可能被 resolve 的情况
type: any;
// 对于原生 DOM 节点,保存实际 DOM 节点的引用
// 对于组件,保存组件实例
stateNode: any;
}
1.2. Fiber 树结构相关
树结构相关,比如 return 代表父级节点
interface FiberNode {
// 指向父级 Fiber 节点
return: Fiber | null;
// 指向第一个子 Fiber 节点
child: Fiber | null;
// 指向下一个兄弟 Fiber 节点
sibling: Fiber | null;
// 索引号,用于处理数组类型的子节点
index: number;
// 指向旧树中对应的 Fiber 节点
alternate: Fiber | null;
}
1.3. 状态和副作用相关
interface FiberNode {
// setState
// 待更新队列,存储 setState 的更新
updateQueue: UpdateQueue<any> | null;
// 当前的状态
memoizedState: any;
// 待处理的 props
pendingProps: any;
// 已经处理完的 props
memoizedProps: any;
// 副作用标记,表示节点需要执行的操作
// 如:Placement、Update、Deletion 等
flags: Flags;
// 子树中的副作用标记
subtreeFlags: Flags;
// 指向下一个有副作用的 Fiber 节点
nextEffect: Fiber | null;
// 副作用链表的第一个和最后一个节点
firstEffect: Fiber | null;
lastEffect: Fiber | null;
}
1.4. 优先级相关
interface FiberNode {
// 任务的优先级
lanes: Lanes;
// 子树的优先级
childLanes: Lanes;
// 替代树的优先级
alternateLanes: Lanes;
}
1.5. 工作进度相关
interface FiberNode {
// 记录已经处理到的 Hook 位置
nextHook: Hook | null;
// 工作进行到的时间
expirationTime: ExpirationTime;
}
1.6. 主要属性的使用场景
1.6.1. 节点更新流程
function updateFiberNode(fiber: FiberNode) {
// 1. 检查更新优先级
if (fiber.lanes === NoLanes) {
return;
}
// 2. 处理 props 更新
if (fiber.pendingProps !== fiber.memoizedProps) {
// 需要更新
fiber.flags |= Update;
}
// 3. 处理状态更新
const updateQueue = fiber.updateQueue;
if (updateQueue !== null) {
processUpdateQueue(fiber, updateQueue);
}
// 4. 处理副作用
if (fiber.flags !== NoFlags) {
// 将当前节点加入副作用链表
scheduleCallback(fiber);
}
}
1.6.2. Fiber 树的遍历
function traverseFiber(fiber: FiberNode) {
let nextFiber = fiber;
while (nextFiber !== null) {
// 1. 处理当前节点
processNode(nextFiber);
// 2. 深度优先遍历
if (nextFiber.child) {
nextFiber = nextFiber.child;
continue;
}
// 3. 没有子节点,处理兄弟节点
while (nextFiber.sibling === null) {
if (nextFiber.return === null || nextFiber.return === fiber) {
return;
}
nextFiber = nextFiber.return;
}
nextFiber = nextFiber.sibling;
}
}
1.6.3. 状态更新示例
function updateState(fiber: FiberNode, update: Update) {
// 1. 创建或获取更新队列
const updateQueue = fiber.updateQueue || createUpdateQueue();
// 2. 将更新添加到队列
enqueueUpdate(updateQueue, update);
// 3. 标记需要更新
fiber.flags |= Update;
// 4. 设置更新优先级
const lane = requestUpdateLane();
fiber.lanes |= lane;
// 5. 向上标记父节点的 childLanes
let parent = fiber.return;
while (parent !== null) {
parent.childLanes |= lane;
parent = parent.return;
}
}
1.6.4. 副作用处理
function commitWork(fiber: FiberNode) {
// 1. 检查副作用标记
if (fiber.flags & Placement) {
// 处理节点插入
commitPlacement(fiber);
}
if (fiber.flags & Update) {
// 处理节点更新
commitUpdate(fiber);
}
if (fiber.flags & Deletion) {
// 处理节点删除
commitDeletion(fiber);
}
// 2. 处理生命周期和 hooks 的副作用
if (fiber.flags & PassiveEffect) {
schedulePassiveEffects(fiber);
}
}
1.6.5. 优先级调度
function scheduleFiberWork(fiber: FiberNode, lane: Lane) {
// 1. 设置当前工作的优先级
fiber.lanes |= lane;
// 2. 向上传播优先级
let parent = fiber.return;
while (parent !== null) {
parent.childLanes |= lane;
parent = parent.return;
}
// 3. 根据优先级调度工作
scheduleCallback(
getCurrentPriorityLevel(),
performConcurrentWorkOnRoot.bind(null, root)
);
}
1.7. 注意事项
-
内存管理
- 及时清理不需要的 Fiber 节点
- 重用 alternate 节点以减少内存分配
-
优先级处理
- 正确设置和传播优先级
- 考虑任务中断和恢复
-
副作用管理
- 合理使用 flags 标记
- 维护好副作用链表
-
状态一致性
- 确保 memoizedState 和 memoizedProps 的正确性
- 处理好 updateQueue 的更新顺序
2. 篇二
2.1. 节点标识和类型属性
class FiberNode {
tag: WorkTag; // 标识节点类型(函数组件、类组件、原生组件等)
key: null | string; // React元素的key属性
elementType: any; // 元素类型
type: any; // 对于函数组件,是函数本身;对于类组件,是类
stateNode: any; // 指向实际DOM节点或组件实例
}
这些属性用于标识和存储 Fiber 节点的基本信息,帮助 React 识别和管理不同类型的组件
2.2. Fiber ==树结构==相关属性
class FiberNode {
return: Fiber | null; // 指向父 Fiber 节点
child: Fiber | null; // 指向第一个子 Fiber 节点
sibling: Fiber | null; // 指向下一个兄弟 Fiber 节点
index: number; // 在兄弟节点中的索引
ref: any; // ref 属性
}
这些属性构建了 Fiber 树的基本结构,使 ==React 能够在树中进行遍历和更新==。
2.3. 工作单元相关属性
class FiberNode {
pendingProps: any; // 新的待处理 props
memoizedProps: any; // 上一次渲染使用的 props
updateQueue: UpdateQueue<any> | null; // 更新队列
memoizedState: any; // 上一次渲染使用的 state
dependencies: Dependencies | null; // 依赖项(context、事件等)
}
这些属性用于管理组件的状态和属性更新,是实现组件渲染和更新的核心。
2.4. 副作用相关属性
class FiberNode {
flags: Flags; // 副作用标记(需要执行的操作类型)
subtreeFlags: Flags; // 子树的副作用标记
deletions: Array<Fiber> | null; // 需要删除的子节点
lanes: Lanes; // 优先级相关
childLanes: Lanes; // 子节点的优先级
}
这些属性用于标记和追踪需要在 ==commit 阶段==执行的副作用操作。
2.5. 调度相关属性
class FiberNode {
alternate: Fiber | null; // 指向内存中另一个版本的 fiber
nextEffect: Fiber | null; // 指向下一个有副作用的 fiber
firstEffect: Fiber | null; // 子树中第一个有副作用的 fiber
lastEffect: Fiber | null; // 子树中最后一个有副作用的 fiber
}
这些属性用于实现 React 的==双缓冲机制==和==副作用链表==,支持==增量渲染和优先级调度==
2.6. 属性的使用场景
2.6.1. 渲染阶段
function beginWork(current: Fiber | null, workInProgress: Fiber) {
// 使用 tag 确定组件类型
switch (workInProgress.tag) {
case FunctionComponent: {
// 处理函数组件
const Component = workInProgress.type;
const props = workInProgress.pendingProps;
// ...
}
// ...其他类型处理
}
}
2.6.2. 提交阶段
function commitWork(current: Fiber | null, finishedWork: Fiber) {
// 根据 flags 执行相应的 DOM 操作
if (finishedWork.flags & Update) {
// 更新 DOM
const instance = finishedWork.stateNode;
// ...
}
}
2.6.3. 调度优先级
function markUpdateLaneFromFiberToRoot(fiber: Fiber) {
// 设置更新优先级
fiber.lanes = mergeLanes(fiber.lanes, lane);
let alternate = fiber.alternate;
if (alternate !== null) {
alternate.lanes = mergeLanes(alternate.lanes, lane);
}
// ...
}
2.7. 重要注意点
-
性能影响
- 属性访问应该避免深层遍历
- 合理使用 memoization 减少不必要的更新
- 注意内存占用,及时清理不需要的引用
-
调试技巧
- 使用 React DevTools 查看 Fiber 树结构
- 通过 flags 追踪更新过程
- 监控 lanes 了解优先级变化
-
常见陷阱
- 避免直接修改 Fiber 节点属性
- 注意处理 null 值
- 正确处理副作用清理
通过深入理解这些属性,我们可以更好地理解 React 的工作原理,编写更高效的 React 应用。