React19源码阅读之commitRoot

commitRoot入口

在finishConcurrentRender函数,commitRootWhenReady函数,commitRoot函数。

commitRoot流程图

commitRoot函数

commitRoot 函数是 React 渲染流程中用于提交根节点的关键函数。它的主要作用是设置相关的优先级和状态,然后调用 commitRootImpl 函数来实际执行根节点的提交操作,最后在操作完成后恢复之前的状态。

函数参数含义

  1. root: 类型为 FiberRoot,代表 React 应用的根节点,包含了整个应用的渲染信息。
  2. recoverableErrors: 类型为 null | Array<CapturedValue<mixed>>,是一个可恢复错误的数组,用于处理在渲染过程中捕获到的可恢复错误。
  3. transitions: 类型为 Array<Transition> | null,表示渲染过程中涉及的过渡任务数组。
  4. didIncludeRenderPhaseUpdate: 布尔类型,指示渲染阶段是否包含更新操作。
  5. spawnedLane: 类型为 Lane,表示在渲染过程中产生的新的渲染优先级车道。
  6. updatedLanes: 类型为 Lanes,表示在渲染过程中更新的渲染优先级车道。
  7. suspendedRetryLanes: 类型为 Lanes,表示暂停后重试的渲染优先级车道。
  8. suspendedCommitReason: 类型为 SuspendedCommitReason,是一个仅用于性能分析的参数,指示提交操作被暂停的原因。
  9. completedRenderStartTime: 数值类型,是一个仅用于性能分析的参数,记录渲染开始的时间。
  10. completedRenderEndTime: 数值类型,是一个仅用于性能分析的参数,记录渲染结束的时间。
function commitRoot(root: FiberRoot,recoverableErrors: null | Array<CapturedValue<mixed>>,transitions: Array<Transition> | null,didIncludeRenderPhaseUpdate: boolean,spawnedLane: Lane,updatedLanes: Lanes,suspendedRetryLanes: Lanes,// suspendedCommitReason: SuspendedCommitReason, // Profiling-only// completedRenderStartTime: number, // Profiling-only// completedRenderEndTime: number, // Profiling-only
) {const prevTransition = ReactSharedInternals.T;const previousUpdateLanePriority = getCurrentUpdatePriority();try {// 设置新的更新优先级并清空过渡状态setCurrentUpdatePriority(DiscreteEventPriority);ReactSharedInternals.T = null;commitRootImpl(root,recoverableErrors,transitions,didIncludeRenderPhaseUpdate,previousUpdateLanePriority,spawnedLane,updatedLanes,suspendedRetryLanes,suspendedCommitReason,completedRenderStartTime,completedRenderEndTime,);} finally {// 恢复之前的状态ReactSharedInternals.T = prevTransition;setCurrentUpdatePriority(previousUpdateLanePriority);}
}

commitRootImpl函数

commitRootImpl 函数是 React 渲染流程中用于提交根节点的核心函数,它负责将渲染阶段生成的结果应用到实际的 DOM 上,并执行相关的副作用操作。

  1. 更新 DOM:将 Fiber 树的变化应用到真实的 DOM 上,完成视图的更新。
  2. 执行副作用:处理各种副作用,包括 useEffectuseLayoutEffect 等钩子函数的执行,以及生命周期方法的调用。
  3. 清理和重置状态:在提交完成后,清理和重置相关的状态,为下一次渲染做准备
function commitRootImpl(root: FiberRoot,recoverableErrors: null | Array<CapturedValue<mixed>>,transitions: Array<Transition> | null,didIncludeRenderPhaseUpdate: boolean,renderPriorityLevel: EventPriority,spawnedLane: Lane,updatedLanes: Lanes,suspendedRetryLanes: Lanes,// suspendedCommitReason: SuspendedCommitReason, // Profiling-only// completedRenderStartTime: number, // Profiling-only// completedRenderEndTime: number, // Profiling-only
) {// 循环调用 flushPassiveEffects 函数,直到没有待处理的被动副作用。// 被动副作用通常包括 useEffect 钩子函数的执行。do {flushPassiveEffects();} while (rootWithPendingPassiveEffects !== null);// 获取已完成的 Fiber 树(finishedWork)和已完成的优先级车道(lanes)。const finishedWork = root.finishedWork;const lanes = root.finishedLanes;// 如果没有已完成的 Fiber 树,则直接返回。if (finishedWork === null) {return null;} // 将 root.finishedWork 和 root.finishedLanes 重置。root.finishedWork = null;root.finishedLanes = NoLanes;// 重置根节点的回调节点、回调优先级和取消待提交的状态。root.callbackNode = null;root.callbackPriority = NoLane;root.cancelPendingCommit = null;// 合并 finishedWork 的车道和子车道,得到剩余的优先级车道let remainingLanes = mergeLanes(finishedWork.lanes, finishedWork.childLanes);// 获取在渲染阶段并发更新的车道。const concurrentlyUpdatedLanes = getConcurrentlyUpdatedLanes();// 合并车道remainingLanes = mergeLanes(remainingLanes, concurrentlyUpdatedLanes);// 将 didIncludeCommitPhaseUpdate 标志重置为 false,用于检测提交阶段是否有递归更新。didIncludeCommitPhaseUpdate = false;// 如果根节点和工作进度根节点一致,则重置相关状态。if (root === workInProgressRoot) {// We can reset these now that they are finished.workInProgressRoot = null;workInProgress = null;workInProgressRootRenderLanes = NoLanes;} // 检查子树是否有 BeforeMutation、Mutation、Layout 或 Passive 副作用。const subtreeHasEffects =(finishedWork.subtreeFlags &(BeforeMutationMask | MutationMask | LayoutMask | PassiveMask)) !==NoFlags;// 检查根节点是否有 BeforeMutation、Mutation、Layout 或 Passive 副作用。const rootHasEffect =(finishedWork.flags &(BeforeMutationMask | MutationMask | LayoutMask | PassiveMask)) !==NoFlags;if (subtreeHasEffects || rootHasEffect) {const prevTransition = ReactSharedInternals.T;ReactSharedInternals.T = null;const previousPriority = getCurrentUpdatePriority();setCurrentUpdatePriority(DiscreteEventPriority);const prevExecutionContext = executionContext;executionContext |= CommitContext;// Before Mutation 阶段const shouldFireAfterActiveInstanceBlur = commitBeforeMutationEffects(root,finishedWork,);// Mutation 阶段// 执行 commitMutationEffects 函数,将 Fiber 树的变化应用到真实的 DOM 上。commitMutationEffects(root, finishedWork, lanes);if (enableCreateEventHandleAPI) {if (shouldFireAfterActiveInstanceBlur) {afterActiveInstanceBlur();}}resetAfterCommit(root.containerInfo);root.current = finishedWork;// Layout 阶段// 执行 commitLayoutEffects 函数,调用 useLayoutEffect 钩子函数和相关的生命周期方法。commitLayoutEffects(finishedWork, root, lanes);// 请求浏览器进行绘制,更新视图。requestPaint();// 恢复上下文和优先级executionContext = prevExecutionContext;setCurrentUpdatePriority(previousPriority);ReactSharedInternals.T = prevTransition;} else {// No effects.root.current = finishedWork;}const rootDidHavePassiveEffects = rootDoesHavePassiveEffects;// 如果根节点有被动副作用,则将相关状态存储起来,等待后续处理;否则,释放根节点的缓存池。if (rootDoesHavePassiveEffects) {rootDoesHavePassiveEffects = false;rootWithPendingPassiveEffects = root;pendingPassiveEffectsLanes = lanes;} else {releaseRootPooledCache(root, remainingLanes);}// Read this again, since an effect might have updated it
// 获取根节点的待处理优先级车道,如果没有剩余工作,则清除已失败的错误边界。remainingLanes = root.pendingLanes;//处理剩余工作和调度if (remainingLanes === NoLanes) {legacyErrorBoundariesThatAlreadyFailed = null;}// 确保根节点被正确调度,以便处理后续的更新。ensureRootIsScheduled(root);// Read this again, since a passive effect might have updated itremainingLanes = root.pendingLanes;// 检测无限更新循环,检测是否存在无限更新循环,若存在则增加嵌套更新计数。if ((enableInfiniteRenderLoopDetection &&(didIncludeRenderPhaseUpdate || didIncludeCommitPhaseUpdate)) ||// Was the finished render the result of an update (not hydration)?(includesSomeLane(lanes, UpdateLanes) &&// Did it schedule a sync update?includesSomeLane(remainingLanes, SyncUpdateLanes))) {if (root === rootWithNestedUpdates) {nestedUpdateCount++;} else {nestedUpdateCount = 0;rootWithNestedUpdates = root;}} else {nestedUpdateCount = 0;}// If layout work was scheduled, flush it now.// 刷新同步工作flushSyncWorkOnAllRoots();return null;
}

当根节点或子节点存在BeforeMutation、Mutation、Layout 或 Passiv副作用时,会执行:

  1. commitBeforeMutationEffects,是 React 渲染流程中提交阶段的一部分,主要用于在进行 DOM 突变(如更新、插入、删除节点)之前执行一些必要的准备工作和副作用操作。该函数会处理焦点管理、标记需要执行的副作用,并返回一个布尔值,指示是否应该触发在活动实例失去焦点后执行的回调。
  2. commitMutationEffects,数是 React 渲染流程中提交阶段的关键部分,它主要负责执行 DOM 突变(如插入、更新、删除节点)相关的副作用操作。此函数会在 React 完成协调阶段(reconciliation)后,将计算出的 DOM 变更应用到实际的 DOM 树上。
  3. commitLayoutEffects,是 React 提交阶段(Commit Phase)中的一个关键函数,主要负责执行布局副作用(Layout Effects)。在 React 的渲染流程中,当协调阶段(Reconciliation Phase)完成后,会进入提交阶段,这个阶段会将协调阶段计算出的变更应用到实际的 DOM 上。布局副作用是在 DOM 更新后立即执行的副作用,通常用于获取 DOM 节点的布局信息,如元素的宽度、高度等。
  4. requestPaint,用于请求浏览器进行一次重绘操作。

flushPassiveEffects函数

flushPassiveEffects 函数主要用于处理 React 中的被动副作用(passive effects)。被动副作用通常是指在渲染完成后异步执行的副作用,例如 useEffect 钩子中的一些操作。该函数会检查是否存在待处理的被动副作用,如果存在,则调用 flushPassiveEffectsImpl 函数来实际执行这些副作用,并在执行前后进行状态的保存和恢复,确保操作的正确性和状态的一致性。

function flushPassiveEffects(wasDelayedCommit?: boolean): boolean {
// rootWithPendingPassiveEffects 是一个全局变量,用于存储存在待处理被动副作用的根节点。
//如果该变量不为 null,则表示存在待处理的被动副作用,继续执行后续操作。if (rootWithPendingPassiveEffects !== null) {// 获取存在待处理被动副作用的根节点。const root = rootWithPendingPassiveEffects;// 获取待处理被动副作用剩余的渲染优先级车道。const remainingLanes = pendingPassiveEffectsRemainingLanes;// 将待处理被动副作用剩余的渲染优先级车道重置为 NoLanes,表示已经开始处理这些副作用。pendingPassiveEffectsRemainingLanes = NoLanes;// lanesToEventPriority 函数将待处理被动副作用的渲染优先级车道转换为事件优先级。const renderPriority = lanesToEventPriority(pendingPassiveEffectsLanes);// 调用 lowerEventPriority 函数,取 DefaultEventPriority 和 renderPriority 中的较低优先级作为最终的执行优先级const priority = lowerEventPriority(DefaultEventPriority, renderPriority);const prevTransition = ReactSharedInternals.T;// 当前的更新优先级const previousPriority = getCurrentUpdatePriority();try {setCurrentUpdatePriority(priority);ReactSharedInternals.T = null;// 调用 flushPassiveEffectsImpl 函数实际执行被动副作用,并返回该函数的执行结果。return flushPassiveEffectsImpl(wasDelayedCommit);} finally {// 恢复之前的状态并释放根节点的缓存setCurrentUpdatePriority(previousPriority);ReactSharedInternals.T = prevTransition;// 释放根节点的缓存,传入根节点和剩余的渲染优先级车道作为参数。releaseRootPooledCache(root, remainingLanes);}}// 不存在待处理的被动副作用,直接返回 false。return false;
}

flushPassiveEffectsImpl

flushPassiveEffectsImpl 函数的主要作用是刷新待处理的被动副作用。被动副作用通常和 React 的 useEffect 钩子相关,在渲染完成后异步执行。此函数会处理组件卸载和挂载时的被动副作用,同时处理过渡回调和同步工作。

function flushPassiveEffectsImpl(wasDelayedCommit: void | boolean) {// 检查是否有待处理的被动副作用if (rootWithPendingPassiveEffects === null) {return false;}// Cache and clear the transitions flag// 缓存并清除过渡标志const transitions = pendingPassiveTransitions;pendingPassiveTransitions = null;// 获取根节点和车道信息并重置const root = rootWithPendingPassiveEffects;const lanes = pendingPassiveEffectsLanes;rootWithPendingPassiveEffects = null;pendingPassiveEffectsLanes = NoLanes;// 检查是否正在渲染if ((executionContext & (RenderContext | CommitContext)) !== NoContext) {throw new Error('Cannot flush passive effects while already rendering.');}// 记录开始时间并设置执行上下文let passiveEffectStartTime = 0;const prevExecutionContext = executionContext;executionContext |= CommitContext;// 执行被动卸载和挂载副作用commitPassiveUnmountEffects(root.current);commitPassiveMountEffects(root,root.current,lanes,transitions,pendingPassiveEffectsRenderEndTime,);// 恢复执行上下文executionContext = prevExecutionContext;// 刷新所有根节点的同步工作flushSyncWorkOnAllRoots();// 若启用了过渡跟踪功能,缓存当前的过渡回调、根节点过渡回调和结束时间。若这些值都不为 null,将当前的过渡回调和结束时间重置为 null,并在空闲调度优先级下调度 processTransitionCallbacks 函数来处理过渡回调。if (enableTransitionTracing) {const prevPendingTransitionCallbacks = currentPendingTransitionCallbacks;const prevRootTransitionCallbacks = root.transitionCallbacks;const prevEndTime = currentEndTime;if (prevPendingTransitionCallbacks !== null &&prevRootTransitionCallbacks !== null &&prevEndTime !== null) {currentPendingTransitionCallbacks = null;currentEndTime = null;scheduleCallback(IdleSchedulerPriority, () => {processTransitionCallbacks(prevPendingTransitionCallbacks,prevEndTime,prevRootTransitionCallbacks,);});}}return true;
}

commitPassiveUnmountEffects

function commitPassiveUnmountEffects(finishedWork: Fiber): void {// resetComponentEffectTimers();commitPassiveUnmountOnFiber(finishedWork);
}

commitPassiveUnmountOnFiber

commitPassiveUnmountOnFiber 函数的主要作用是在 React 渲染流程的提交阶段,对指定的 Fiber 节点执行被动卸载副作用的操作。被动卸载副作用通常与 useEffect 钩子的清理函数相关,当组件卸载时,这些清理函数会被调用。该函数会根据 Fiber 节点的不同类型,执行相应的卸载逻辑。

function commitPassiveUnmountOnFiber(finishedWork: Fiber): void {// const prevEffectStart = pushComponentEffectStart();switch (finishedWork.tag) {case FunctionComponent:case ForwardRef:case SimpleMemoComponent: {recursivelyTraversePassiveUnmountEffects(finishedWork);if (finishedWork.flags & Passive) {commitHookPassiveUnmountEffects(finishedWork,finishedWork.return,HookPassive | HookHasEffect,);}break;}case HostRoot: {// const prevEffectDuration = pushNestedEffectDurations();recursivelyTraversePassiveUnmountEffects(finishedWork);break;}case Profiler: {// const prevEffectDuration = pushNestedEffectDurations();recursivelyTraversePassiveUnmountEffects(finishedWork);break;}case OffscreenComponent: {const instance: OffscreenInstance = finishedWork.stateNode;const nextState: OffscreenState | null = finishedWork.memoizedState;const isHidden = nextState !== null;if (isHidden &&instance._visibility & OffscreenPassiveEffectsConnected &&(finishedWork.return === null ||finishedWork.return.tag !== SuspenseComponent)) {instance._visibility &= ~OffscreenPassiveEffectsConnected;recursivelyTraverseDisconnectPassiveEffects(finishedWork);} else {recursivelyTraversePassiveUnmountEffects(finishedWork);}break;}default: {recursivelyTraversePassiveUnmountEffects(finishedWork);break;}}// popComponentEffectStart(prevEffectStart);
}

recursivelyTraversePassiveUnmountEffects

递归遍历 Fiber 树,处理组件卸载时的被动副作用(如 useEffect 的清理函数)。它主要处理两类逻辑:

  1. 子节点删除:当父节点标记为需要删除子节点(ChildDeletion)时,遍历所有待删除的子节点,执行其被动卸载副作用。
  2. 子树被动副作用:遍历父节点的子树,对每个子节点调用 commitPassiveUnmountOnFiber,处理其被动卸载逻辑。
function recursivelyTraversePassiveUnmountEffects(parentFiber: Fiber): void {const deletions = parentFiber.deletions;// 如果父节点有子节点需要删除if ((parentFiber.flags & ChildDeletion) !== NoFlags) {if (deletions !== null) {for (let i = 0; i < deletions.length; i++) {const childToDelete = deletions[i];//当前要删除的子节点nextEffect = childToDelete;// 在子节点被删除前,执行其被动卸载副作用。commitPassiveUnmountEffectsInsideOfDeletedTree_begin(childToDelete,parentFiber,);}}// 断开已删除子节点的兄弟节点与旧 Fiber 树(alternate 指针)的连接,避免残留引用导致内存泄漏。detachAlternateSiblings(parentFiber);}// 遍历子树处理被动副作用if (parentFiber.subtreeFlags & PassiveMask) {let child = parentFiber.child;while (child !== null) {// 深度优先commitPassiveUnmountOnFiber(child);// 兄弟节点(广度优先)child = child.sibling;}}
}


commitPassiveUnmountEffectsInsideOfDeletedTree_begin

主要功能是在删除子树时,递归地执行该子树中所有 Fiber 节点的被动卸载副作用。它会遍历子树中的每个 Fiber 节点,对每个节点调用 commitPassiveUnmountInsideDeletedTreeOnFiber 函数来执行具体的卸载逻辑。

function commitPassiveUnmountEffectsInsideOfDeletedTree_begin(deletedSubtreeRoot: Fiber,nearestMountedAncestor: Fiber | null,
) {// 循环遍历 Fiber 节点while (nextEffect !== null) {const fiber = nextEffect;commitPassiveUnmountInsideDeletedTreeOnFiber(fiber, nearestMountedAncestor);// 处理子节点const child = fiber.child;if (child !== null) {child.return = fiber;nextEffect = child;} else {commitPassiveUnmountEffectsInsideOfDeletedTree_complete(deletedSubtreeRoot,);}}
}

commitPassiveUnmountEffectsInsideOfDeletedTree_complete

ommitPassiveUnmountEffectsInsideOfDeletedTree_complete 函数的主要功能是在删除子树的被动卸载副作用处理完成后,对删除子树中的 Fiber 节点进行清理工作,确保内存能够被正确释放,避免出现内存泄漏问题。它会遍历子树中的 Fiber 节点,逐个清理节点及其关联资源,并且在遍历过程中根据节点的兄弟节点和父节点信息进行路径回溯。

function commitPassiveUnmountEffectsInsideOfDeletedTree_complete(deletedSubtreeRoot: Fiber,
) {// 循环遍历 Fiber 节点while (nextEffect !== null) {const fiber = nextEffect;const sibling = fiber.sibling;const returnFiber = fiber.return;// 清理 Fiber 节点及其关联的资源,确保内存释放和旧节点引用断开。detachFiberAfterEffects(fiber);// 判断是否到达删除子树的根节点if (fiber === deletedSubtreeRoot) {nextEffect = null;return;}// 处理兄弟节点if (sibling !== null) {sibling.return = returnFiber;nextEffect = sibling;return;}// 回溯父节点nextEffect = returnFiber;}
}

commitPassiveUnmountInsideDeletedTreeOnFiber

function commitPassiveUnmountInsideDeletedTreeOnFiber(current: Fiber,nearestMountedAncestor: Fiber | null,
): void {switch (current.tag) {case FunctionComponent:case ForwardRef:case SimpleMemoComponent: {commitHookPassiveUnmountEffects(current,nearestMountedAncestor,HookPassive,);break;}case LegacyHiddenComponent:case OffscreenComponent: {if (enableCache) {if (current.memoizedState !== null &&current.memoizedState.cachePool !== null) {const cache: Cache = current.memoizedState.cachePool.pool;if (cache != null) {retainCache(cache);}}}break;}case SuspenseComponent: {if (enableTransitionTracing) {// We need to mark this fiber's parents as deletedconst offscreenFiber: Fiber = (current.child: any);const instance: OffscreenInstance = offscreenFiber.stateNode;const transitions = instance._transitions;if (transitions !== null) {const abortReason = {reason: 'suspense',name: current.memoizedProps.unstable_name || null,};if (current.memoizedState === null ||current.memoizedState.dehydrated === null) {abortParentMarkerTransitionsForDeletedFiber(offscreenFiber,abortReason,transitions,instance,true,);if (nearestMountedAncestor !== null) {abortParentMarkerTransitionsForDeletedFiber(nearestMountedAncestor,abortReason,transitions,instance,false,);}}}}break;}case CacheComponent: {if (enableCache) {const cache = current.memoizedState.cache;releaseCache(cache);}break;}case TracingMarkerComponent: {if (enableTransitionTracing) {// We need to mark this fiber's parents as deletedconst instance: TracingMarkerInstance = current.stateNode;const transitions = instance.transitions;if (transitions !== null) {const abortReason = {reason: 'marker',name: current.memoizedProps.name,};abortParentMarkerTransitionsForDeletedFiber(current,abortReason,transitions,null,true,);if (nearestMountedAncestor !== null) {abortParentMarkerTransitionsForDeletedFiber(nearestMountedAncestor,abortReason,transitions,null,false,);}}}break;}}
}

detachAlternateSiblings

detachAlternateSiblings 函数的主要作用是断开父 Fiber 节点旧版本(alternate)的子节点之间的兄弟关系。

当需要清理旧的 Fiber 节点时,该函数会将旧 Fiber 节点的子节点之间的兄弟引用断开,从而辅助垃圾回收机制更有效地回收这些不再使用的旧节点。

function detachAlternateSiblings(parentFiber: Fiber) {const previousFiber = parentFiber.alternate;if (previousFiber !== null) {// 检查旧版本父节点是否有子节点let detachedChild = previousFiber.child;if (detachedChild !== null) {// 开父节点与第一个子节点的连接。previousFiber.child = null;//  遍历并断开子节点的兄弟关系do {// 下一个子节点(兄弟节点)const detachedSibling = detachedChild.sibling;//断开其与兄弟节点的连接。detachedChild.sibling = null;detachedChild = detachedSibling;} while (detachedChild !== null);}}
}

commitPassiveUnmountOnFiber

commitPassiveUnmountOnFiber 函数的主要作用是在 React 渲染流程的提交阶段,对指定的 Fiber 节点执行被动卸载副作用的操作。被动卸载副作用通常与 useEffect 钩子的清理函数相关,当组件卸载时,这些清理函数会被调用。该函数会根据 Fiber 节点的不同类型,执行相应的卸载逻辑。

function commitPassiveUnmountOnFiber(finishedWork: Fiber): void {// const prevEffectStart = pushComponentEffectStart();switch (finishedWork.tag) {case FunctionComponent:case ForwardRef:case SimpleMemoComponent: {recursivelyTraversePassiveUnmountEffects(finishedWork);if (finishedWork.flags & Passive) {commitHookPassiveUnmountEffects(finishedWork,finishedWork.return,HookPassive | HookHasEffect,);}break;}case HostRoot: {// const prevEffectDuration = pushNestedEffectDurations();recursivelyTraversePassiveUnmountEffects(finishedWork);break;}case Profiler: {// const prevEffectDuration = pushNestedEffectDurations();recursivelyTraversePassiveUnmountEffects(finishedWork);break;}case OffscreenComponent: {const instance: OffscreenInstance = finishedWork.stateNode;const nextState: OffscreenState | null = finishedWork.memoizedState;const isHidden = nextState !== null;if (isHidden &&instance._visibility & OffscreenPassiveEffectsConnected &&(finishedWork.return === null ||finishedWork.return.tag !== SuspenseComponent)) {instance._visibility &= ~OffscreenPassiveEffectsConnected;recursivelyTraverseDisconnectPassiveEffects(finishedWork);} else {recursivelyTraversePassiveUnmountEffects(finishedWork);}break;}default: {recursivelyTraversePassiveUnmountEffects(finishedWork);break;}}// popComponentEffectStart(prevEffectStart);
}

commitHookPassiveUnmountEffects

function commitHookPassiveUnmountEffects(finishedWork: Fiber,nearestMountedAncestor: null | Fiber,hookFlags: HookFlags,
) {commitHookEffectListUnmount(hookFlags,finishedWork,nearestMountedAncestor,);
}

commitHookEffectListUnmount

commitHookEffectListUnmount 函数的主要功能是在 React 组件卸载时,对符合特定标志(flags)的副作用钩子(如 useEffectuseLayoutEffect 等)执行清理操作。在 React 中,副作用钩子可能会返回一个清理函数,用于在组件卸载时进行资源释放、取消订阅等操作,该函数就是负责调用这些清理函数的。

函数参数含义

  • flags: 类型为 HookFlags,是一个位掩码,用于筛选需要执行卸载操作的副作用钩子。不同的标志代表不同类型的副作用钩子,例如 Layout 标志可能对应 useLayoutEffectPassive 标志可能对应 useEffect
  • finishedWork: 类型为 Fiber,表示已经完成协调的 Fiber 节点,该节点包含了组件的副作用钩子信息。
  • nearestMountedAncestor: 类型为 Fiber | null,表示距离 finishedWork 最近的已挂载的祖先 Fiber 节点,在执行清理操作时可能会用到。
function commitHookEffectListUnmount(flags: HookFlags,finishedWork: Fiber,nearestMountedAncestor: Fiber | null,
) {try {// 获取副作用队列const updateQueue = finishedWork.updateQueue;// 获取最后一个const lastEffect = updateQueue !== null ? updateQueue.lastEffect : null;if (lastEffect !== null) {const firstEffect = lastEffect.next;let effect = firstEffect;do {// 检查当前副作用的 tag 是否与传入的 flags 匹配。如果匹配,说明该副作用需要执行卸载操作。if ((effect.tag & flags) === flags) {// Unmountconst inst = effect.inst;const destroy = inst.destroy;if (destroy !== undefined) {// 将 inst.destroy 设置为 undefined,表示清理函数已经执行过inst.destroy = undefined;// 调用 safelyCallDestroy 函数安全地执行清理函数safelyCallDestroy(finishedWork, nearestMountedAncestor, destroy);}}effect = effect.next;} while (effect !== firstEffect);}} catch (error) {// captureCommitPhaseError(finishedWork, finishedWork.return, error);}
}

flushSyncWorkOnAllRoots

function performSyncWorkOnRoot(root: FiberRoot, lanes: Lanes) {// This is the entry point for synchronous tasks that don't go// through Scheduler.const didFlushPassiveEffects = flushPassiveEffects();if (didFlushPassiveEffects) {return null;}const forceSync = true;performWorkOnRoot(root, lanes, forceSync);
}

工具函数之 detachFiberAfterEffects

detachFiberAfterEffects 函数的作用是在 React 组件卸载或更新完成后,清理 Fiber 节点及其关联的资源,确保内存释放和旧节点引用断开。它主要用于处理已完成副作用(如 DOM 更新、钩子回调)的 Fiber 节点,避免内存泄漏,并为后续的垃圾回收做准备。

function detachFiberAfterEffects(fiber: Fiber) {// 断开 alternate 引用并递归清理const alternate = fiber.alternate;if (alternate !== null) {fiber.alternate = null;detachFiberAfterEffects(alternate);}// 清空子节点和副作用相关属性fiber.child = null;fiber.deletions = null;fiber.sibling = null;// 处理宿主组件(如 DOM 节点)if (fiber.tag === HostComponent) {const hostInstance: Instance = fiber.stateNode;if (hostInstance !== null) {// 调用该函数清理 DOM 节点的关联资源(如事件监听器、自定义数据),确保 DOM 节点安全卸载。detachDeletedInstance(hostInstance);}}// 清空 stateNode(指向真实 DOM 节点的引用),避免内存泄漏。fiber.stateNode = null;// 重置 Fiber 节点状态fiber.return = null;fiber.dependencies = null;fiber.memoizedProps = null;fiber.memoizedState = null;fiber.pendingProps = null;fiber.stateNode = null;fiber.updateQueue = null;
}

工具函数之 detachDeletedInstance

function detachDeletedInstance(node: Instance): void {delete (node: any)[internalInstanceKey];delete (node: any)[internalPropsKey];delete (node: any)[internalEventHandlersKey];delete (node: any)[internalEventHandlerListenersKey];delete (node: any)[internalEventHandlesSetKey];
}

const randomKey = Math.random().toString(36).slice(2);
const internalInstanceKey = '__reactFiber$' + randomKey;
const internalPropsKey = '__reactProps$' + randomKey;
const internalContainerInstanceKey = '__reactContainer$' + randomKey;
const internalEventHandlersKey = '__reactEvents$' + randomKey;
const internalEventHandlerListenersKey = '__reactListeners$' + randomKey;
const internalEventHandlesSetKey = '__reactHandles$' + randomKey;
const internalRootNodeResourcesKey = '__reactResources$' + randomKey;
const internalHoistableMarker = '__reactMarker$' + randomKey;

工具函数之 lanesToEventPriority

lanesToEventPriority 函数的主要功能是将 React 的车道(Lanes)转换为对应的事件优先级(EventPriority)。在 React 的并发模式下,车道系统用于管理不同优先级的更新任务,而事件优先级则用于确定事件处理的紧急程度。该函数会根据传入的车道信息,找出最高优先级的车道,并将其映射为合适的事件优先级。

参数lanes:类型为 Lanes,表示一组车道。在 React 中,Lanes 是一种用于表示多个优先级车道的位掩码数据结构,每个车道代表一个不同的优先级。

function lanesToEventPriority(lanes: Lanes): EventPriority {// 获取最高优先级的车道const lane = getHighestPriorityLane(lanes);// 判断并返回离散事件优先级if (!isHigherEventPriority(DiscreteEventPriority, lane)) {return DiscreteEventPriority;}// 判断并返回连续事件优先级if (!isHigherEventPriority(ContinuousEventPriority, lane)) {return ContinuousEventPriority;}// 判断 lane 是否包含非空闲工作。if (includesNonIdleWork(lane)) {return DefaultEventPriority;}// 返回空闲事件优先级return IdleEventPriority;
}

// 表示没有事件优先级,它被映射到 NoLane。const NoEventPriority: EventPriority = NoLane;// 离散事件优先级,映射到 SyncLane。离散事件通常是指那些由用户交互触发的不连续事件,如点击、输入等。SyncLane 表示同步车道,这类事件的更新任务会被立即同步执行,以保证用户交互的即时响应。const DiscreteEventPriority: EventPriority = SyncLane;// 连续事件优先级,对应 InputContinuousLane。连续事件一般是指那些持续的用户交互事件,如滚动、拖动等。InputContinuousLane 用于处理这类连续事件的更新任务,确保在连续交互过程中页面的流畅性。const ContinuousEventPriority: EventPriority = InputContinuousLane;// 默认事件优先级,映射到 DefaultLane。当没有指定特定的事件优先级时,会使用默认优先级。DefaultLane 是一种通用的车道,用于处理大多数普通的更新任务。const DefaultEventPriority: EventPriority = DefaultLane;// 空闲事件优先级,对应 IdleLane。空闲事件是指那些在浏览器空闲时才会执行的任务,对实时性要求较低。IdleLane 中的任务会在浏览器有空闲资源时才会被执行,以避免影响其他高优先级任务的执行。const IdleEventPriority: EventPriority = IdleLane;

工具函数之 lowerEventPriority

lowerEventPriority 函数的主要功能是比较两个事件优先级(EventPriority),并返回其中较低的优先级。在 React 的协调和调度机制中,事件优先级用于决定不同任务的执行顺序,确保高优先级的任务能够优先得到处理。

函数参数含义

  • a:类型为 EventPriority,代表第一个需要比较的事件优先级。
  • b:类型为 EventPriority,代表第二个需要比较的事件优先级。

使用三元运算符进行条件判断,具体逻辑如下:

  • a === 0:如果 a 的值为 0,在 React 的优先级体系中,0 可能代表一种特殊的优先级(如最高优先级或者无优先级的特殊情况),此时直接返回 a
  • a > b:如果 a 的值大于 b,根据 React 中事件优先级的定义,值越大优先级越低,所以返回 a
  • 其他情况:如果上述两个条件都不满足,即 a 不为 0 且 a 小于等于 b,则返回 b
function lowerEventPriority(a: EventPriority,b: EventPriority,
): EventPriority {return a === 0 || a > b ? a : b;
}

工具函数之 mergeLanes

mergeLanes 函数的主要功能是合并两个车道(Lanes 或单个 Lane)。在 React 的调度系统里,车道(Lanes)机制用于对不同更新任务的优先级进行管理和区分。该函数借助按位或运算符 | 把两个车道合并成一个新的车道,从而将多个更新任务的优先级信息整合起来。

 function mergeLanes(a: Lanes | Lane, b: Lanes | Lane): Lanes {return a | b;
}const LaneA = 0b0001; // 二进制表示,代表第 1 个车道
const LaneB = 0b0010; // 二进制表示,代表第 2 个车道const mergedLanes = mergeLanes(LaneA, LaneB);
console.log(mergedLanes.toString(2)); // 输出: 0b0011,代表第 1 个和第 2 个车道的合并

工具函数之 getCurrentUpdatePriority

function getCurrentUpdatePriority(): EventPriority {return currentUpdatePriority;
}

工具函数之 setCurrentUpdatePriority

let currentUpdatePriority: EventPriority = NoEventPriority;function setCurrentUpdatePriority(newPriority: EventPriority): void {currentUpdatePriority = newPriority;
}

工具函数之 safelyCallDestroy

 function safelyCallDestroy(current: Fiber,// 已完成的fibernearestMountedAncestor: Fiber | null,destroy: () => void,
) {try {// 执行清理回调函数destroy();} catch (error) {// captureCommitPhaseError(current, nearestMountedAncestor, error);}
}

工具函数之 detachDeletedInstance

清除实例上的某些属性。调用该函数清理 DOM 节点的关联资源(如事件监听器、自定义数据),确保 DOM 节点安全卸载。

function detachDeletedInstance(node: Instance): void {delete (node: any)[internalInstanceKey];delete (node: any)[internalPropsKey];delete (node: any)[internalEventHandlersKey];delete (node: any)[internalEventHandlerListenersKey];delete (node: any)[internalEventHandlesSetKey];
}

const randomKey = Math.random().toString(36).slice(2);
const internalInstanceKey = '__reactFiber$' + randomKey;
const internalPropsKey = '__reactProps$' + randomKey;
const internalContainerInstanceKey = '__reactContainer$' + randomKey;
const internalEventHandlersKey = '__reactEvents$' + randomKey;
const internalEventHandlerListenersKey = '__reactListeners$' + randomKey;
const internalEventHandlesSetKey = '__reactHandles$' + randomKey;
const internalRootNodeResourcesKey = '__reactResources$' + randomKey;
const internalHoistableMarker = '__reactMarker$' + randomKey;

全局变量之事件优先级

// 表示没有优先级(初始状态或无效状态)。
export const NoEventPriority: EventPriority = NoLane;
// 离散事件优先级,最高优先级。用于需要立即同步执行的操作,如用户交互(点击、键盘事件)、setState 同步更新。这类操作会打断其他低优先级任务,立即执行。
export const DiscreteEventPriority: EventPriority = SyncLane;
// 连续事件优先级,用于连续触发的事件(如鼠标移动、滚动)。这类操作允许中断低优先级任务,但可以与其他连续任务合并,避免过度渲染。
export const ContinuousEventPriority: EventPriority = InputContinuousLane;
// 默认优先级,用于普通的状态更新(如异步数据加载完成后的更新)。任务会在离散和连续事件之后执行,但比空闲任务优先。
export const DefaultEventPriority: EventPriority = DefaultLane;
// 空闲优先级,最低优先级。用于非紧急任务(如性能优化、统计上报),仅在浏览器空闲时执行,可能被高优先级任务中断或丢弃。
export const IdleEventPriority: EventPriority = IdleLane;

const TotalLanes = 31;const NoLanes: Lanes = /*                 */ 0b0000000000000000000000000000000;
const NoLane: Lane = /*                   */ 0b0000000000000000000000000000000;const SyncHydrationLane: Lane = /*        */ 0b0000000000000000000000000000001;
const SyncLane: Lane = /*                 */ 0b0000000000000000000000000000010;
const SyncLaneIndex: number = 1;
const InputContinuousHydrationLane:Lane= /**/0b0000000000000000000000000000100;
const InputContinuousLane: Lane = /*      */ 0b0000000000000000000000000001000;const DefaultHydrationLane: Lane = /*     */ 0b0000000000000000000000000010000;
const DefaultLane: Lane = /*              */ 0b0000000000000000000000000100000;const SyncUpdateLanes: Lane = SyncLane | InputContinuousLane | DefaultLane;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/902730.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

利用Python爬虫实现百度图片搜索的PNG图片下载

在图像识别、训练数据集构建等场景中&#xff0c;我们经常需要从互联网上批量下载图片素材。百度图片是中文搜索中最常用的来源之一。本文将介绍如何使用Python构建一个稳定、可扩展的百度图片爬虫&#xff0c;专门用于下载并保存高清PNG格式图片。 一、项目目标 本项目的目标…

Axure复选框组件的深度定制:实现自定义大小、颜色与全选功能

在产品设计中&#xff0c;复选框作为用户与界面交互的重要元素&#xff0c;其灵活性直接影响到用户体验。本文将介绍如何利用Axure RP工具&#xff0c;通过高级技巧实现复选框组件的自定义大小、颜色调整&#xff0c;以及全选功能的集成&#xff0c;为产品原型设计增添更多可能…

深度理解spring——BeanFactory的实现

BeanFactory Spring之BeanFactory什么是BeanFactoryApplicationContext相对BeanFactory实现的功能性扩展1. MessageSource2. ResourcePatternResolver3. ApplicationEventPublisher4. EnvironmentCapable通用ApplicationContext实践实现BeanFactoryBeanFactory后处理器排序让谁…

跑MPS产生委外采购申请(成品)

问题&#xff1a;跑MPS产生委外采购申请&#xff08;成品&#xff09;&#xff0c;更改BOM和跑MRP&#xff0c;但物料需求清单中无新增物料复合膜的需求。截图如下&#xff1a; 解决方法&#xff1a;更改委外采购申请的批准日期为BOM的生效日和重新展开bom。 重新展开后&#x…

“在中国,为中国” 英飞凌汽车业务正式发布中国本土化战略

3月28日&#xff0c;以“夯实电动化&#xff0c;推进智能化&#xff0c;实现高质量发展”为主题的2025中国电动汽车百人会论坛在北京举办。众多中外机构与行业上下游嘉宾就全球及中国汽车电动化的发展现状、面临的挑战与机遇&#xff0c;以及在技术创新、市场布局、供应链协同等…

优雅实现网页弹窗提示功能:JavaScript与CSS完美结合

在现代Web开发中&#xff0c;弹窗提示是提升用户体验的重要元素之一。本文将深入探讨如何实现一个优雅、可复用的弹窗提示系统&#xff0c;避免常见问题如重复触发、样式混乱等。 核心代码解析 // 控制弹窗是否可以显示的标志 let alertStatus true;// 显示提示信息 functio…

YOLOv11改进-双Backbone架构:利用双backbone提高yolo11目标检测的精度

一、引言&#xff1a;为什么我们需要双Backbone&#xff1f; 在目标检测任务中&#xff0c;YOLO系列模型因其高效的端到端检测能力而备受青睐。然而&#xff0c;传统YOLO模型大多采用单一Backbone结构&#xff0c;即利用一个卷积神经网络&#xff08;CNN&#xff09;作为特征提…

用 PyQt5 和 asyncio 打造接口并发测试 GUI 工具

接口并发测试是测试工程师日常工作中的重要一环&#xff0c;而一个直观的 GUI 工具能有效提升工作效率和体验。本篇文章将带你用 PyQt5 和 asyncio 从零实现一个美观且功能实用的接口并发测试工具。 我们将实现以下功能&#xff1a; 请求方法选择器 添加了一个下拉框 QComboBo…

理解npm的工作原理:优化你的项目依赖管理流程

目录 什么是npm npm核心功能 npm 常用指令及其作用 执行npm i 发生了什么? 1. 解析命令与参数 2. 检查依赖文件 3. 依赖版本解析与树构建 4. 缓存检查与包下载 5. 解压包到 node_modules 6. 更新 package-lock.json 7. 处理特殊依赖类型 8. 执行生命周期脚本 9. …

React Native 安卓端 android Image 播放gif webp 动态图

React Native 安卓端 android Image 播放gif webp 动态图 RN项目是0.78.2 React是19.0 基本介绍 Image 是 React Native 中用于显示各种类型图片的核心组件&#xff0c;支持显示网络图片、静态资源、本地图片以及 base64 编码的图片。在 Android 端&#xff0c;Image 组件还可…

实时数字人——DH_LIVE

前两天亲手搭建了实时对话数字人VideoChat&#xff0c;今天来搭建下DH_LIVE。 DH_LIVE一个实时数字人解决方案&#xff0c;从输入文字到数字人对口型说话用时2-3秒。 今天就来实际操作下dh_live的搭建过程。 首先贴上git地址&#xff1a;https://github.com/kleinlee/DH_liv…

AOSP CachedAppOptimizer 冻结方案

背景 Android 一直面临一个核心难题&#xff1a;如何优化进程对有限系统资源&#xff08;如 CPU、电量&#xff09;的使用&#xff0c;同时保证用户体验。 当进程进入后台后&#xff0c;它们虽不再贡献用户体验&#xff0c;却仍可能消耗资源。传统的杀后台方案虽然节省资源&a…

实体店的小程序转型之路:拥抱新零售的密码-中小企实战运营和营销工作室博客

实体店的小程序转型之路&#xff1a;拥抱新零售的密码-中小企实战运营和营销工作室博客 在当今数字化浪潮的冲击下&#xff0c;实体店面临着前所未有的挑战&#xff0c;但小程序的出现为实体店转型新零售带来了新的曙光。先来看一组惊人的数据&#xff0c;据相关统计&#xff…

Java求职面试:从Spring Boot到微服务的全面考核

Java求职面试实录&#xff1a;从Spring Boot到微服务的全面考核 第一轮&#xff1a;基础技术的考察 场景&#xff1a; 赵大宝走进了一家互联网大厂的面试间&#xff0c;面试官严肃地看着他。 面试官&#xff1a; 赵大宝&#xff0c;你好。我们先从简单的开始。请你解释一下J…

记录一个坑关于STM32 ARM Compiler Version

在用 Keil 进行 STM32 开发的时候&#xff0c;一开始下载&#xff0c;下载的 ARM 编译器是 Version6&#xff0c;他就不兼容老的代码&#xff0c;就很抽象。 所以必须要更换编译器。 可以去官网下载编译器 Downloads - Arm Developer &#xff0c;也可以自己找资源哈&#xff…

PCIe体系结构学习入门——PCI总线概述(二)PCI总线的桥和配置

这里写目录标题 序言存储器域和 PCI 总线域HOST 主桥PCI 桥和 PCI 设备配置空间PCI 桥PCI 设备配置空间PCI 总线的配置非透明 PCI 桥序言 接续前章内容,本章继续讲述 PCI 总线概述的第二部分——PCI 总线的桥和配置。 如果需要进一步了解前一章节内容,可以访问:PCIe体系结构…

浔川代码编辑器v2.0(测试版)更新公告

浔川代码编辑器v2.0(测试版)更新公告 发布日期&#xff1a;** 2023年4月30日 我们很高兴地宣布浔川代码编辑器v2.0测试版即将上线&#xff01;本次更新带来了多项功能改进和问题修复&#xff0c;旨在为用户提供更稳定、更强大的编程体验。 主要更新内容 1. **Bug修复与稳定性提…

微信小程序 tabbar底部导航栏

官方文档&#xff1a;https://developers.weixin.qq.com/miniprogram/dev/reference/configuration/app.html#tabBar 一、常规菜单格式 在app.json 文件中配置&#xff0c;其他关键点详见官方文档&#xff0c;后续更新不规则图标的写法

Spring 中@Autowired,@Resource,@Inject 注解实现原理

使用案例 前置条件&#xff1a; 现在有一个 Vehicle 接口&#xff0c;它有两个实现类 Bus 和 Car &#xff0c;现在还有一个类 VehicleService 需要注入一个 Vehicle 类型的 Bean&#xff1a; public interface Vehicle {}Component public class Car implements Vehicle {}C…

【Rust结构体】Rust结构体详解:从基础到高级应用

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…