背景
上一篇博客我去了解了jsx是怎么转换为reactElement的过程,那么jsx转换后是怎么整合到完整的dom树中的呢,这就不得不提到reactElement转化为Fiber的过程了
转换逻辑
暂时无法在飞书文档外展示此内容
- Fiber数据结构 源码地址
Fiber数据结构是React Fiber架构的核心部分,用于表示React中的每一个节点。它的作用可以总结如下:
-
节点类型:
tag:区分函数组件、类组件等不同类型的节点。elementType和type:表示节点的类型,通常相同,但在开发环境下可能不同以支持热更新。
-
树结构:
return:指向父节点。child:指向第一个子节点。sibling:指向下一个兄弟节点。index:节点在兄弟节点中的位置。
-
引用:
ref和refCleanup:用于处理组件上的引用。
-
属性和状态:
pendingProps:当前传入的props。memoizedProps:上一次渲染时的props。updateQueue:存储状态更新的队列。memoizedState:当前的状态。
-
依赖:
dependencies:节点的依赖关系。
-
模式:
mode:描述节点及其子树的属性,比如是否是并发模式。
-
副作用:
flags和subtreeFlags:描述节点及其子树的副作用。deletions:需要删除的子节点。
-
优先级:
lanes和childLanes:表示节点及其子节点的优先级。
-
双缓存:
alternate:指向内存中的另一个Fiber节点,用于实现双缓存机制。
这个数据结构使得React能够高效地进行更新和渲染,支持复杂的UI变化和优化。
export type Fiber = {
tag: WorkTag, // 用于区分函数组件或者类组件
key: null | string, // element元素的键值
elementType: any, // element转入的type值
type: any, // 一般与elementType相同,一些特殊情形下, 比如在开发环境下为了兼容热更新
stateNode: any, // 真实连接的dom元素
// 链接部分
return: Fiber | null, // 父亲节点
child: Fiber | null, // 孩子节点
sibling: Fiber | null, // 兄弟节点
index: number,
ref:
| null
| (((handle: mixed) => void) & {_stringRef: ?string, ...})
| RefObject, //指向在ReactElement组件上设置的 ref
refCleanup: null | (() => void),
// 参数与记忆记录
pendingProps: any, // // 从`ReactElement`对象传入的 props. 用于和`fiber.memoizedProps`比较可以得出属性是否变动
memoizedProps: any, // 上一次生成子节点时用到的属性, 生成子节点之后保持在内存中
updateQueue: mixed, // 存储state更新的队列, 当前节点的state改动之后, 都会创建一个update对象添加到这个队列中.
memoizedState: any, // 用于输出的state, 最终渲染所使用的state
dependencies: Dependencies | null,
mode: TypeOfMode,
// Effect
flags: Flags,
subtreeFlags: Flags,
deletions: Array<Fiber> | null,
// 优先级相关
lanes: Lanes, // 本fiber节点的优先级
childLanes: Lanes, // 子节点的优先级
alternate: Fiber | null, // 双fiber缓存 指向内存中的另一个fiber, 每个被更新过fiber节点在内存中都是成对出现(current和workInProgress)
|};
//...其它
};
对应构造函数 FiberNode
FiberNode函数的作用是创建一个新的Fiber节点实例。这个函数初始化了一个Fiber节点的所有属性。
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
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;
//...其它
}
- createFiberFromTypeAndProps 源码地址
函数的作用是根据传入的类型和属性创建一个新的 Fiber 节点。具体来说,它会根据组件类型(如函数组件、类组件、原生组件等)和属性来创建相应的 Fiber 对象,并设置 Fiber 的各种属性以便 React 在协调和渲染过程中使用。
export function createFiberFromTypeAndProps(
type: any, // React$ElementType
key: null | string,
pendingProps: any,
owner: null | ReactComponentInfo | Fiber,
mode: TypeOfMode,
lanes: Lanes,
): Fiber {
let fiberTag = FunctionComponent;
// 根据传入的type进行fiberTag判断,基本分为函数型,对象,字符
let resolvedType = type;
if (typeof type === 'function') {
if (shouldConstruct(type)) {
fiberTag = ClassComponent;
if (__DEV__) {
resolvedType = resolveClassForHotReloading(resolvedType);
}
} else {
if (__DEV__) {
resolvedType = resolveFunctionForHotReloading(resolvedType);
}
}
} else if (typeof type === 'string') {
if (supportsResources && supportsSingletons) {
const hostContext = getHostContext();
fiberTag = isHostHoistableType(type, pendingProps, hostContext)
? HostHoistable
: isHostSingletonType(type)
? HostSingleton
: HostComponent;
} else if (supportsResources) {
const hostContext = getHostContext();
fiberTag = isHostHoistableType(type, pendingProps, hostContext)
? HostHoistable
: HostComponent;
} else if (supportsSingletons) {
fiberTag = isHostSingletonType(type) ? HostSingleton : HostComponent;
} else {
fiberTag = HostComponent;
}
} else {
getTag: switch (type) {
case ... // 根据type的值进行归类判断
return ... // 调用不同类型的Fiber构造函数
// Fall through
default: {
// ...对出现的异常状况做处理
}
}
}
const fiber = createFiber(fiberTag, pendingProps, key, mode);
// 为新创建的fiber属性赋值
fiber.elementType = type;
fiber.type = resolvedType;
fiber.lanes = lanes;
return fiber;
}
- createFiber 源码地址
createFiber的选择有enableObjectFiber决定,即是否允许直接使用对象(包含fiber创建需要的所有参数)创建fiber对象,否则则使用createFiberImplClass构造(即调用上文提到的FiberNode)新的fiber对象
const createFiber = enableObjectFiber
? createFiberImplObject
: createFiberImplClass;
结语
哈哈哈,今天就到这里啦,或许后面会继续学习保持更新吧