在上一篇文章,看了createRoot
函数的大致流程。
createContainer
函数创建并返回了FiberRoot
。FiberRoot
是由createFiberRoot
函数创建,createFiberRoot
函数还将FiberRoot
和根Fiber
通过current
属性建立起了联系。- 将
FiberRoot
作为参数传给ReactDOMRoot
构造函数,返回带有_internalRoot
属性(其实就是参数FiberRoot
),render
和unmount
方法的ReactDOMRoot实例对象
。
下面就继续来看一下 FiberRoot
和 Fiber
是如何创建以及他们的各自的属性都具体什么含义。
FiberRootNode 构造函数
FiberRootNode
用于创建一个 FiberRootNode
实例,这个实例包含了与整个 React 应用渲染过程相关的各种状态和信息,如挂载的 DOM 容器、当前的 Fiber
树、优先级管理、错误处理回调、表单状态等,为 React 协调器管理和调度整个应用的渲染工作提供了基础。
函数参数含义:
●containerInfo
:表示挂载 React 应用的 DOM 容器的信息,通常是一个 DOM 元素,如 document.getElementById(‘root’) 返回的元素。
●tag
:用于标识 React 应用的启动模式,可能是并发模式或传统模式。
●hydrate
:与服务端渲染的水合(hydration)相关的参数,用于指示是否进行水合操作。
●identifierPrefix
:标识符前缀,可能用于生成唯一的标识符。
●onUncaughtError
:未捕获错误的回调函数,当应用中出现未捕获的错误时会调用该函数。
●onCaughtError
:捕获错误的回调函数,用于处理已捕获的错误。
●onRecoverableError
:可恢复错误的回调函数,用于处理可以恢复的错误。
●formState
:表单状态,可能包含表单的输入值、验证状态等信息。
function FiberRootNode(
this: $FlowFixMe,
containerInfo: any,
// $FlowFixMe[missing-local-annot]
tag,
hydrate: any,
identifierPrefix: any,
onUncaughtError: any,
onCaughtError: any,
onRecoverableError: any,
formState: ReactFormState<any, any> | null,
) {
// 启动模式和容器
this.tag = disableLegacyMode ? ConcurrentRoot : tag;//启动模式: 1并发模式,0传统模式
this.containerInfo = containerInfo;// 挂载DOM容器的信息
// fiber
this.pendingChildren = null;// 指向下一个 Fiber 节点树的指针,通常在更新过程中用于存储待处理的子节点。
this.current = null;//指向当前 Fiber 节点的指针,代表当前正在渲染的 Fiber 树。
this.pingCache = null;// 用于缓存 FiberNode 的引用,以便快速访问。
this.finishedWork = null;//存储完成的 Fiber 节点,通常在渲染完成后更新。
// 超时和取消
this.timeoutHandle = noTimeout;// 处理超时的句柄,初始值为 noTimeout,用于管理渲染过程中的超时情况。
this.cancelPendingCommit = null;// 用于取消挂起的提交操作的函数,初始值为 null。
//上下文
this.context = null; // 当前的上下文对象,用于在组件树中传递数据。
this.pendingContext = null;// 当前挂起的上下文,在上下文更新时使用。
// 链表
this.next = null; // 指向下一个 FiberRootNode 对象的指针,用于构建链表结构。
// 回调
this.callbackNode = null;// 指向回调函数的 Fiber 节点的指针,用于管理回调函数的执行。
this.callbackPriority = NoLane;// 回调优先级
this.expirationTimes = createLaneMap(NoTimestamp);// 一个存储各个 Lane 过期时间的映射,通过 createLaneMap 函数创建,初始值为 NoTimestamp。
//优先级
this.pendingLanes = NoLanes; // 代表待处理的车道集合。NoLanes 表明目前没有待处理的更新任务。
this.suspendedLanes = NoLanes; // 表示被挂起的车道集合。在某些情形下,更新任务可能会因为数据未就绪等原因而被挂起。
this.pingedLanes = NoLanes;//指需要处理的车道集合。当某个车道被标记为需要处理时,会被添加到这个集合中。
this.warmLanes = NoLanes;// 与预热渲染相关的车道集合。预热渲染一般用于提前准备数据或进行一些预计算。
this.expiredLanes = NoLanes; // 代表已过期的车道集合。若某个更新任务的优先级较低,且等待时间过长,就可能会过期。
this.finishedLanes = NoLanes; // 表示已完成的车道集合。当某个更新任务成功完成后,对应的车道会被添加到这个集合中。
this.errorRecoveryDisabledLanes = NoLanes;// 表示禁用错误恢复的车道集合。在某些情况下,可能会禁用某些车道的错误恢复机制。
this.shellSuspendCounter = 0;// 挂起计数器
this.entangledLanes = NoLanes;// 相关联的 Lane
this.entanglements = createLaneMap(NoLanes);// 相关联的 Lane 的映射
this.hiddenUpdates = createLaneMap(null); // 隐藏更新的 Lane 的映射
this.identifierPrefix = identifierPrefix; // 标识符前缀
// 回调
this.onUncaughtError = onUncaughtError;
this.onCaughtError = onCaughtError;
this.onRecoverableError = onRecoverableError;// 可恢复错误的回调函数
// 如果 enableCache 为 true,则初始化缓存相关的属性,包括缓存的 FiberNode 和缓存的 Lane。
if (enableCache) {
this.pooledCache = null; // 缓存的 FiberNode
this.pooledCacheLanes = NoLanes;// 缓存的 Lane
}
// 如果 enableSuspenseCallback 为 true,则初始化水合回调函数相关的属性。
if (enableSuspenseCallback) {
this.hydrationCallbacks = null;// 用于注水的回调函数
}
this.formState = formState; // 表单状态
// 一个 Map 对象,用于存储未完成的过渡信息。
this.incompleteTransitions = new Map();// 未完成的过渡的映射
// 如果 enableTransitionTracing 为 true,则初始化过渡回调函数和过渡 Lane 映射。
if (enableTransitionTracing) {
this.transitionCallbacks = null;
const transitionLanesMap = (this.transitionLanes = []);
for (let i = 0; i < TotalLanes; i++) {
transitionLanesMap.push(null);
}
}
// 如果 enableProfilerTimer 和 enableProfilerCommitHooks 都为 true,则初始化性能分析相关的属性,用于记录副作用和被动副作用的持续时间。
// if (enableProfilerTimer && enableProfilerCommitHooks) {
// this.effectDuration = -0;
// this.passiveEffectDuration = -0;
// }
// 如果 enableUpdaterTracking 为 true,则初始化更新跟踪相关的属性,包括存储已记忆的更新器和每个 Lane 的待处理更新器集合。
if (enableUpdaterTracking) {
this.memoizedUpdaters = new Set();
const pendingUpdatersLaneMap = (this.pendingUpdatersLaneMap = []);
for (let i = 0; i < TotalLanes; i++) {
pendingUpdatersLaneMap.push(new Set());
}
}
}
createFiber 函数
createFiber
函数,根据组件类型调用不同的函数,默认enableObjectFiber
为true
,调用createFiberImplObject
函数,否则调用createFiberImplClass
函数。
const createFiber = enableObjectFiber
? createFiberImplObject
: createFiberImplClass;
createFiberImplObject
createFiberImplObject
函数是用于创建一个 Fiber
对象的具体实现,Fiber
对象是 React Fiber
架构中的核心数据结构,代表了一个 React 元素或组件的工作单元。该函数根据传入的参数初始化 Fiber
对象的各种属性,这些属性用于描述组件的状态、结构以及在渲染过程中的相关信息。
函数参数含义:
●tag
:类型为 WorkTag,表示 Fiber 节点的类型,例如 HostComponent、FunctionComponent 等,不同的类型决定了 Fiber 节点在渲染过程中的不同处理方式。
●pendingProps
:类型为 mixed,表示即将传递给组件的属性,这些属性可能会在后续的渲染过程中被使用。
●key
:类型为 null 或 string,用于唯一标识 Fiber 节点,在 React 进行列表渲染时,key 可以帮助 React 更高效地进行元素的更新和重排。
●mode
:类型为 TypeOfMode,表示 Fiber 节点的模式,例如并发模式、严格模式等,不同的模式会影响 React 的渲染行为。
function createFiberImplObject(
tag: WorkTag,// 3代表根节点
pendingProps: mixed,// 即将传递给组件的属性。
key: null | string,
mode: TypeOfMode,// 渲染模式 并发模式或者传统模式
): Fiber {
// 初始化 Fiber 对象
const fiber: Fiber = {
// Instance
// tag, key - defined at the bottom as dynamic properties
elementType: null,// 通常存储 React 元素的类型,如函数组件、类组件或 DOM 元素类型,初始化为 null。
type: null,// 与 elementType 类似,但在某些情况下可能会有不同的含义,初始化为 null。
stateNode: null,// 存储与 Fiber 节点关联的实际 DOM 节点或组件实例,初始化为 null。
// Fiber
return: null,// 指向父 Fiber 节点,用于在渲染完成后返回上一级。
child: null,// 指向第一个子 Fiber 节点。
sibling: null,// 指向下一个兄弟 Fiber 节点。
index: 0,// 表示当前 Fiber 节点在兄弟节点中的索引位置,初始化为 0。
ref: null,// 用于存储 ref 对象,方便获取组件或 DOM 节点的引用。
refCleanup: null,// 用于清理 ref 相关的资源,初始化为 null。
// pendingProps - defined at the bottom as dynamic properties
memoizedProps: null,// 上一次渲染时使用的属性,初始化为 null。
updateQueue: null,// 存储组件的更新队列,初始化为 null。
memoizedState: null,// 存储组件的状态,初始化为 null。
dependencies: null,// 存储组件的依赖项,初始化为 null。
// Effects
flags: NoFlags,// 表示 Fiber 节点的副作用标记,初始化为 NoFlags,表示没有副作用。
subtreeFlags: NoFlags,// 表示子树的副作用标记,初始化为 NoFlags。
deletions: null,// 存储需要删除的子 Fiber 节点,初始化为 null。
lanes: NoLanes,// 表示当前 Fiber 节点的优先级车道,初始化为 NoLanes。
childLanes: NoLanes,// 表示子 Fiber 节点的优先级车道,初始化为 NoLanes。
alternate: null,// 双缓存,指向的另一个版本的fiber
// dynamic properties at the end for more efficient hermes bytecode
tag,// fiber类型
key,// 用于唯一标识 Fiber 节点
pendingProps,// 即将传递给组件的属性。
mode,// Fiber 节点的模式,例如并发模式、严格模式等
};
// 启用了性能分析器
if (enableProfilerTimer) {
fiber.actualDuration = -0;// 表示 Fiber 节点实际渲染所花费的时间
fiber.actualStartTime = -1.1;// 表示 Fiber 节点开始渲染的时间
fiber.selfBaseDuration = -0;// 表示 Fiber 节点自身的基本渲染时间
fiber.treeBaseDuration = -0;// 表示 Fiber 节点及其子树的基本渲染时间
}
// 返回 Fiber 对象
return fiber;
}
createFiberImplClass
createFiberImplClass
函数是用于创建 Fiber
节点的另一种实现方式,它通过实例化 FiberNode
类来创建一个 Fiber 对象。
function createFiberImplClass(
tag: WorkTag,
pendingProps: mixed,
key: null | string,
mode: TypeOfMode,
): Fiber {
// $FlowFixMe[invalid-constructor]: the shapes are exact here but Flow doesn't like constructors
return new FiberNode(tag, pendingProps, key, mode);
}
FiberNode 构造函数
FiberNode
是一个构造函数,用于创建 React 的 Fiber
节点。
函数参数含义:
●tag
: WorkTag:tag 是一个 WorkTag 类型的值,用于标识 Fiber 节点的类型,例如是函数组件、类组件、原生 DOM 元素等。不同的 tag 值对应不同的处理逻辑。
●pendingProps
: mixed:pendingProps 表示当前节点的待处理属性,是一个任意类型的值。这些属性是从父组件传递过来的,在节点的处理过程中可能会被更新。
●key
: null | string:key 是一个可选的字符串,用于帮助 React 识别哪些元素发生了变化,提高列表渲染的性能。如果没有提供 key,则为 null。
●mode
: TypeOfMode:mode 表示节点的模式,它定义了节点的一些行为和特性,例如是否处于严格模式等。
function FiberNode(
this: $FlowFixMe,
tag: WorkTag,
pendingProps: mixed,
key: null | string,
mode: TypeOfMode,
) {
// Instance
this.tag = tag;
this.key = key;
this.elementType = null;
this.type = null;
this.stateNode = null;// 存储与该 Fiber 节点对应的实际 DOM 节点或组件实例,初始化为 null。
// Fiber
this.return = null;
this.child = null;
this.sibling = null;
this.index = 0;
this.ref = null;
this.refCleanup = null;
this.pendingProps = pendingProps;
this.memoizedProps = null;
this.updateQueue = null;
this.memoizedState = null;
this.dependencies = null;
this.mode = mode;
// Effects
this.flags = NoFlags;
this.subtreeFlags = NoFlags;
this.deletions = null;
this.lanes = NoLanes;
this.childLanes = NoLanes;
this.alternate = null;
// if (enableProfilerTimer) {
// this.actualDuration = -0;
// this.actualStartTime = -1.1;
// this.selfBaseDuration = -0;
// this.treeBaseDuration = -0;
// }
}