在 初步认识 React 中的 fiber 中介绍了什么是 Fiber 以及 Fiber 的类型。
本文将介绍如何创建 Fiber 和 FiberRoot。
创建 Fiber
React 使用 createFiber 函数创建 Fiber,实际上是实例化了 FiberNode。
export function createFiber(
tag: WorkTag,
pendingProps: any,
key: null | string
): Fiber {
return new FiberNode(tag, pendingProps, key);
}
function FiberNode(tag: WorkTag, pendingProps: any, key: null | string) {
// 标记fiber的类型,即描述的组件类型,如原生标签、函数组件、类组件、Fragment等。这里参考ReactWorkTags.js
this.tag = tag;
// 定义组件在当前层级下的唯一性
// 标记组件在当前层级下的的唯一性
this.key = key;
// 组件类型
this.elementType = null;
// 组件类型
this.type = null;
// 不同的组件的 stateNode 定义也不同
// 原生标签:string
// 类组件:实例
this.stateNode = null;
// Fiber
// return 过程中维护 effect 链表
this.return = null;
this.child = null;
this.sibling = null;
// 记录了节点在兄弟节点中的位置下标,用于diff时候判断节点是否需要发生移动
this.index = 0;
this.pendingProps = pendingProps;
this.memoizedProps = null;
// 不同的组件的 memoizedState 指代也不同
// 函数组件 hook0
// 类组件 state
this.memoizedState = null;
// Effects
// effect 链表存放整颗 fiber 树中更新的 fiber 节点
this.flags = NoFlags;
this.nextEffect = null;
this.firstEffect = null;
this.lastEffect = null;
// 缓存fiber
this.alternate = null;
this.deletions = null;
// 记录effect
this.updateQueue = null;
this.lanes = NoLanes;
this.childLanes = NoLanes;
}
另外还有根据 ReactElement 创建 Fiber。
// 根据 ReactElement 创建Fiber
export function createFiberFromElement(element: ReactElement) {
const { type, key } = element;
const pendingProps = element.props;
const fiber = createFiberFromTypeAndProps(type, key, pendingProps);
return fiber;
}
// 根据 type 获取 tag
export function createFiberFromTypeAndProps(
type: any,
key: null | string,
pendingProps: any
) {
let fiberTag: WorkTag = IndeterminateComponent;
if (isFn(type)) {
// 函数组件、类组件
if (type.prototype.isReactComponent) {
fiberTag = ClassComponent;
} else {
fiberTag = FunctionComponent;
}
} else if (isStr(type)) {
// 原生标签
fiberTag = HostComponent;
} else if (type === REACT_FRAGMENT_TYPE) {
fiberTag = Fragment;
} else if (type.$$typeof === REACT_PROVIDER_TYPE) {
fiberTag = ContextProvider;
} else if (type.$$typeof === REACT_CONTEXT_TYPE) {
fiberTag = ContextConsumer;
} else if (type.$$typeof === REACT_MEMO_TYPE) {
fiberTag = MemoComponent;
}
const fiber = createFiber(fiberTag, pendingProps, key);
fiber.elementType = type;
fiber.type = type;
return fiber;
}
创建 FiberRoot
先看下 FiberRoot 类型。
export type Container = Element | Document | DocumentFragment;
export type FiberRoot = {
containerInfo: Container;
current: Fiber;
// 一个准备提交 work-in-progress, HostRoot
finishedWork: Fiber | null;
pendingLanes: Lanes;
};
createFiberRoot 实例化了 FiberRootNode。
FiberRootNode 的 current 属性值是一个 fiber,通过 createFiber 函数创建。
export function createFiberRoot(containerInfo: Container): FiberRoot {
const root: FiberRoot = new FiberRootNode(containerInfo);
const uninitializedFiber: Fiber = createFiber(HostRoot, null, null);
root.current = uninitializedFiber;
uninitializedFiber.stateNode = root;
return root;
}
export function FiberRootNode(containerInfo: Container) {
this.containerInfo = containerInfo;
this.current = null;
this.finishedWork = null;
this.pendingLanes = NoLanes;
}