react创建子fiberNode需要当前的current FiberNode和新的reactElement比较创建子fiberNode
- mount阶段会大量插入节点,性能消耗较大(利用构建离屏操作优化性能
- update节点只会更新节点,性能消耗较小
创建beginWork
// packages/react-reconciler/src/ReactFiberBeginWork.ts
export const beginWork = (wip: FiberNode) => {
const tag = wip.tag;
switch (tag) {
case HostRoot:
return updateHostRoot(wip);
case HostComponent:
return updateHostComponent(wip);
case HostText:
return null;
default:
if (__DEV__) {
console.warn('beginWork还未实现的类型');
}
return null;
}
};
创建子fiberNode
updateHostRoot 根元素 对应的子fiberNode
const updateHostRoot = (wip: FiberNode) => {
const baseState = wip.memoizedState;
const updateQueue = wip.updateQueue as UpdateQueue<Element>;
const pending = updateQueue.shared.pending; // 新的属性,用于更新赋值
updateQueue.shared.pending = null; // 新值被使用了,就把新值变成null
// 开始更新
const { memoizedState } = processUpdateQueue(baseState, pending);
wip.memoizedState = memoizedState;
// 创建子fiberNode
const nextChildren = wip.memoizedState;
reconcilerChildren(wip, nextChildren);
return wip.child;
};
普通元素节点对应的fiberNode
// 元素节点没有更新操作,只生成子fiberNode
function updateHostComponent(wip: FiberNode) {
const nextProps = wip.pendingProps;
const nextChildren = nextProps.children;
reconcilerChildren(wip, nextChildren);
return wip.child;
}
创建子fiberNode
function reconcilerChildren(wip: FiberNode, children?: ReactElement) {
const current = wip.alternate;
if (current !== null) {
// update
wip.child = reconcileChildrenFibers(wip, current.child, children);
} else {
// mount
wip.child = mountChildrenFibers(wip, null, children);
}
}
// /packages/react-reconciler/src/ReactChildFiber.ts
import { ReactElement } from 'shared/ReactTypes';
import { createFiberFromElement, FiberNode } from './ReactFiber';
import { REACT_ELEMENT_TYPE } from 'shared/ReactSymbols';
import { HostText } from './ReactWorkTags';
import { Placement } from './ReactFiberFlags';
function childReconciler(shouldTrackEffects: boolean) {
function reconcileSingleElement(
returnFiber: FiberNode,
currentFiber: FiberNode | null,
newChild: ReactElement,
) {
const fiber = createFiberFromElement(newChild);
fiber.return = returnFiber;
return fiber;
}
function reconcileSingleTextNode(
returnFiber: FiberNode,
currentFiber: FiberNode | null,
content: string | number,
) {
const fiber = new FiberNode(HostText, { content }, null);
fiber.return = returnFiber;
return fiber;
}
// 定义是否shouldTrackEffects
function placeSingleChild(fiber: FiberNode) {
if (shouldTrackEffects && fiber.alternate === null) {
fiber.flags |= Placement;
}
return fiber;
}
return function reconcilerChildFibers(
returnFiber: FiberNode,
currentFiber: FiberNode | null,
newChild?: ReactElement,
) {
// todo
// 根据新的reactElement生成fiberNode
if (typeof newChild === 'object' && newChild !== null) {
switch (newChild.$$typeof) {
case REACT_ELEMENT_TYPE:
return placeSingleChild(
reconcileSingleElement(returnFiber, currentFiber, newChild),
);
default:
if (__DEV__) {
console.warn('未实现的reconcile类型', newChild);
}
break;
}
}
// HostText
if (typeof newChild === 'string' || typeof newChild === 'number') {
return placeSingleChild(
reconcileSingleTextNode(returnFiber, currentFiber, newChild),
);
}
return null;
};
}
export const reconcileChildrenFibers = childReconciler(true);
export const mountChildrenFibers = childReconciler(false);
根据ReactElement创建fiberNode
export function createFiberFromElement(element: ReactElement) {
const { type, key, props } = element;
let fiberTag: WorkTag = FunctionComponent;
if (typeof type === 'string') {
// div type: div
fiberTag = HostComponent;
} else if (typeof type !== 'function' && __DEV__) {
console.warn('未定义的type类型', element);
}
const fiber = new FiberNode(fiberTag, props, key);
fiber.type = type;
return fiber;
}