commit阶段分为三个局部

  • before mutation阶段
  • mutation阶段
  • layout阶段
    次要都是在commitRootImpl函数内进行调用

commitRootImpl

这里只展现调用before mutation阶段的代码

if (firstEffect !== null) {  // 保留之前的优先级,以同步优先级执行,执行结束后复原之前优先级  const previousLanePriority = getCurrentUpdateLanePriority();  setCurrentUpdateLanePriority(SyncLanePriority);    // 将以后上下文标记为CommitContext,作为commit阶段的标记  const prevExecutionContext = executionContext;  executionContext |= CommitContext;  const prevInteractions = pushInteractions(root);  // 在调用生命周期之前将此重置为 null  ReactCurrentOwner.current = null;  // The commit phase is broken into several sub-phases. We do a separate pass  // of the effect list for each phase: all mutation effects come before all  // layout effects, and so on.  // The first phase a "before mutation" phase. We use this phase to read the  // state of the host tree right before we mutate it. This is where  // getSnapshotBeforeUpdate is called.  focusedInstanceHandle = prepareForCommit(root.containerInfo);  shouldFireAfterActiveInstanceBlur = false;  nextEffect = firstEffect;  do {    if (__DEV__) {      //....开发环境下调用      invokeGuardedCallback(null, commitBeforeMutationEffects, null);      if (hasCaughtError()) {        invariant(nextEffect !== null, 'Should be working on an effect.');        const error = clearCaughtError();        captureCommitPhaseError(nextEffect, error);        nextEffect = nextEffect.nextEffect;      }    } else {      try {        // 调用commitBeforeMutationEffects        commitBeforeMutationEffects();      } catch (error) {        invariant(nextEffect !== null, 'Should be working on an effect.');        captureCommitPhaseError(nextEffect, error);        nextEffect = nextEffect.nextEffect;      }    }  } while (nextEffect !== null);  //....}

invokeGuardedCallback

开发环境下调用commitBeforeMutationEffects函数

function invokeGuardedCallback(name, func, context, a, b, c, d, e, f) {  hasError = false;  caughtError = null;  invokeGuardedCallbackImpl$1.apply(reporter, arguments);}

commitBeforeMutationEffects

调用before mutation次要函数

function commitBeforeMutationEffects() {  while (nextEffect !== null) {    const current = nextEffect.alternate;    if (!shouldFireAfterActiveInstanceBlur && focusedInstanceHandle !== null) {      // ...focus blur相干      if ((nextEffect.effectTag & Deletion) !== NoEffect) {        if (doesFiberContain(nextEffect, focusedInstanceHandle)) {          shouldFireAfterActiveInstanceBlur = true;          beforeActiveInstanceBlur();        }      } else {        // TODO: Move this out of the hot path using a dedicated effect tag.        if (          nextEffect.tag === SuspenseComponent &&          isSuspenseBoundaryBeingHidden(current, nextEffect) &&          doesFiberContain(nextEffect, focusedInstanceHandle)        ) {          shouldFireAfterActiveInstanceBlur = true;          beforeActiveInstanceBlur();        }      }    }    const effectTag = nextEffect.effectTag;    if ((effectTag & Snapshot) !== NoEffect) {      setCurrentDebugFiberInDEV(nextEffect);            // 调用getSnapshotBeforeUpdate      commitBeforeMutationEffectOnFiber(current, nextEffect);      resetCurrentDebugFiberInDEV();    }    // 调度useEffect    if ((effectTag & Passive) !== NoEffect) {      // If there are passive effects, schedule a callback to flush at      // the earliest opportunity.      if (!rootDoesHavePassiveEffects) {        rootDoesHavePassiveEffects = true;        scheduleCallback(NormalSchedulerPriority, () => {          flushPassiveEffects();          return null;        });      }    }    nextEffect = nextEffect.nextEffect;  }}

commitBeforeMutationEffectOnFiber

次要判断组件类型,如果是类组件就执行getSnapshotBeforeUpdate生命周期

function commitBeforeMutationLifeCycles(  current: Fiber | null,  finishedWork: Fiber,): void {  switch (finishedWork.tag) {    case FunctionComponent:    case ForwardRef:    case SimpleMemoComponent:    case Block: {      return;    }    case ClassComponent: {      if (finishedWork.effectTag & Snapshot) {        if (current !== null) {          const prevProps = current.memoizedProps;          const prevState = current.memoizedState;          const instance = finishedWork.stateNode;          // We could update instance props and state here,          // but instead we rely on them being set during last render.          // TODO: revisit this when we implement resuming.          if (__DEV__) {               // ....          }          // 调用getSnapshotBeforeUpdate生命周期          const snapshot = instance.getSnapshotBeforeUpdate(            finishedWork.elementType === finishedWork.type              ? prevProps              : resolveDefaultProps(finishedWork.type, prevProps),            prevState,          );          if (__DEV__) {            // ....          }          instance.__reactInternalSnapshotBeforeUpdate = snapshot;        }      }      return;    }    case HostRoot: {      if (supportsMutation) {        if (finishedWork.effectTag & Snapshot) {          const root = finishedWork.stateNode;          clearContainer(root.containerInfo);        }      }      return;    }    case HostComponent:    case HostText:    case HostPortal:    case IncompleteClassComponent:      // Nothing to do for these component types      return;  }  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.',  );}

新版生命周期。

总结

这节次要学习before mutation阶段函数调用流程

  • commitRootImpl是commit阶段次要函数,调用commitBeforeMutationEffects
  • commitBeforeMutationEffects次要性能是:执行commitBeforeMutationEffectOnFiber和通过flushPassiveEffects调度useEffect
  • commitBeforeMutationEffectOnFiber通过判断组件类型次要来执行类组件getSnapshotBeforeUpdate生命周期函数