共计 4377 个字符,预计需要花费 11 分钟才能阅读完成。
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 生命周期函数
正文完
发表至: javascript
2022-04-10