React源码Part6——Commit阶段(beforeMutation)
Posted 冷咖啡
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React源码Part6——Commit阶段(beforeMutation)相关的知识,希望对你有一定的参考价值。
React源码Part-1——代数效应:https://segmentfault.com/a/11...
React源码Part2——渲染原理: https://segmentfault.com/a/11...
React源码Part3——Fiber架构:https://segmentfault.com/a/11...
React源码Part4——Render渲染(Mount阶段):https://segmentfault.com/a/11...
React源码Part4——Render渲染(Update阶段):https://segmentfault.com/a/11...
React源码Part5——commit阶段(处理class组件生命周期): https://segmentfault.com/a/11...
React源码Part7——Commit(Mutation阶段): https://segmentfault.com/a/11...
React源码Part8——Commit(Layout阶段):https://segmentfault.com/a/11...
参考链接:React技术揭秘——https://react.iamkasong.com/p...
beforeMutaion阶段做了什么
- 第一步__入口函数:
commitBeforeMutationEffects()
- 第二步__开始处理Effects链表的单个Fiber节点:
commitBeforeMutationEffects_begin()
- 第三步__遍历Effects链表中每个fiebr节点:
commitBeforeMutationEffects_complete()
- 第四步__处理得到的单个Fibre节点:
commitBeforeMutationEffectsOnFiber()
commitBeforeMutationEffects()
export function commitBeforeMutationEffects(
root: FiberRoot,
firstChild: Fiber,
) {
focusedInstanceHandle = prepareForCommit(root.containerInfo);
// 链表结构的 nextEffect
nextEffect = firstChild;
// 开始执行 BeforeMutationEffects
commitBeforeMutationEffects_begin();
// We no longer need to track the active instance fiber
const shouldFire = shouldFireAfterActiveInstanceBlur;
shouldFireAfterActiveInstanceBlur = false;
focusedInstanceHandle = null;
return shouldFire;
}
commitBeforeMutationEffects_begin()
function commitBeforeMutationEffects_begin() {
// 如果有需要处理的Effect
while (nextEffect !== null) {
const fiber = nextEffect;
// TODO: Should wrap this in flags check, too, as optimization
// 给需要处理的Fiber搭上标记
const deletions = fiber.deletions;
if (deletions !== null) {
for (let i = 0; i < deletions.length; i++) {
const deletion = deletions[i];
commitBeforeMutationEffectsDeletion(deletion);
}
}
const child = fiber.child;
if (
(fiber.subtreeFlags & BeforeMutationMask) !== NoFlags &&
child !== null
) {
// 处理Fibre节点的兄弟节点——这是调度相关
ensureCorrectReturnPointer(child, fiber);
nextEffect = child;
} else {
// 处理单个的Fibre节点
commitBeforeMutationEffects_complete();
}
}
}
commitBeforeMutationEffects_complete()
function commitBeforeMutationEffects_complete() {
while (nextEffect !== null) {
const fiber = nextEffect;
if (__DEV__) {
// DEV 环境的东西可以不管
// ...
} else {
try {
// 处理从Effect链表得到的单个Fiber节点
commitBeforeMutationEffectsOnFiber(fiber);
} catch (error) {
captureCommitPhaseError(fiber, fiber.return, error);
}
}
const sibling = fiber.sibling;
// 处理兄弟节点的Fiber
if (sibling !== null) {
ensureCorrectReturnPointer(sibling, fiber.return);
nextEffect = sibling;
return;
}
nextEffect = fiber.return;
}
}
commitBeforeMutationEffectsOnFiber()
function commitBeforeMutationEffectsOnFiber(finishedWork: Fiber) {
const current = finishedWork.alternate;
const flags = finishedWork.flags;
if (!shouldFireAfterActiveInstanceBlur && focusedInstanceHandle !== null) {
// Check to see if the focused element was inside of a hidden (Suspense) subtree.
// TODO: Move this out of the hot path using a dedicated effect tag.
if (
finishedWork.tag === SuspenseComponent &&
isSuspenseBoundaryBeingHidden(current, finishedWork) &&
doesFiberContain(finishedWork, focusedInstanceHandle)
) {
shouldFireAfterActiveInstanceBlur = true;
beforeActiveInstanceBlur(finishedWork);
}
}
if ((flags & Snapshot) !== NoFlags) {
setCurrentDebugFiberInDEV(finishedWork);
// 根据不同的tag处理对应的事件,
switch (finishedWork.tag) {
case FunctionComponent:
case ForwardRef:
case SimpleMemoComponent: {
break;
}
case ClassComponent: {
if (current !== null) {
const prevProps = current.memoizedProps;
const prevState = current.memoizedState;
const instance = finishedWork.stateNode;
// 对于class组件而言,getSnaoshotBeforeUpdat生命周期在此调用
const snapshot = instance.getSnapshotBeforeUpdate(
finishedWork.elementType === finishedWork.type
? prevProps
: resolveDefaultProps(finishedWork.type, prevProps),
prevState,
);
instance.__reactInternalSnapshotBeforeUpdate = snapshot;
}
break;
}
// 对于函数组件(Hooks)而言,执行的内容
case HostRoot: {
if (supportsMutation) {
const root = finishedWork.stateNode;
clearContainer(root.containerInfo);
}
break;
}
case HostComponent:
case HostText:
case HostPortal:
case IncompleteClassComponent:
// Nothing to do for these component types
break;
default: {
invariant(
false,
\'This unit of work tag should not have side-effects. This error is \' +
\'likely caused by a bug in React. Please file an issue.\',
);
}
}
resetCurrentDebugFiberInDEV();
}
}
以上是关于React源码Part6——Commit阶段(beforeMutation)的主要内容,如果未能解决你的问题,请参考以下文章