React commit阶段解析-前置学习
作者:互联网
在renderRootSync执行完render相关阶段后,就会进入commit阶段。performSyncWorkOnRoot函数执行的末尾调用commitRoot(root);
commit阶段工作
在 rootFiber.firstEffect 上保存了一条需要执行副作用的 Fiber 节点的单向链表effectList,这些 Fiber 节点的 updateQueue 中保存了变化的 props。
除此之外,一些生命周期钩子(比如 componentDidXXX)、hook(比如 useEffect)需要在commit 阶段执行。
commit 阶段的主要工作分为三部分:
- before mutation 阶段(执行 DOM 操作前)
- mutation 阶段(执行 DOM 操作)
- layout 阶段(执行 DOM 操作后)
commitRoot
commit阶段工作起点,把fiberNode传参进去
function commitRoot(root) {
// getCurrentPriorityLevel调度优先级相关
const renderPriorityLevel = getCurrentPriorityLevel();
runWithPriority(
ImmediateSchedulerPriority,
commitRootImpl.bind(null, root, renderPriorityLevel),
);
return null;
}
commitRootImpl
代码300多行, 主要包括commit的前置工作和上文三阶段的执行,下面代码主要是前置部分
commit阶段前置工作:
- 调用flushPassiveEffects执行完所有effect的任务
- 初始化相关变量
- 赋值firstEffect给后面遍历effectList用
function commitRootImpl(root, renderPriorityLevel) {
do {
// 触发 useEffect 回调与其他同步任务。由于这些任务可能触发新的渲染,所以这里要一直遍历执行直到没有任务
flushPassiveEffects();
} while (rootWithPendingPassiveEffects !== null);
// 指向当前应用的rootFiber
const finishedWork = root.finishedWork;
// 优先级
const lanes = root.finishedLanes;
if (finishedWork === null) {
return null;
}
// 重置变量
root.finishedWork = null;
root.finishedLanes = NoLanes;
// Scheduler回调函数重置
root.callbackNode = null;
root.callbackId = NoLanes;
// 合并和清除优先级
let remainingLanes = mergeLanes(finishedWork.lanes, finishedWork.childLanes);
markRootFinished(root, remainingLanes);
// 清除已完成的discrete updates,例如:用户鼠标点击触发的更新。
if (rootsWithPendingDiscreteUpdates !== null) {
if (
!hasDiscreteLanes(remainingLanes) &&
rootsWithPendingDiscreteUpdates.has(root)
) {
rootsWithPendingDiscreteUpdates.delete(root);
}
}
// 重置全局变量
if (root === workInProgressRoot) {
workInProgressRoot = null;
workInProgress = null;
workInProgressRootRenderLanes = NoLanes;
} else {
}
// 将effectList副作用赋值给firstEffect
let firstEffect;
if (finishedWork.effectTag > PerformedWork) {
if (finishedWork.lastEffect !== null) {
finishedWork.lastEffect.nextEffect = finishedWork;
firstEffect = finishedWork.firstEffect;
} else {
firstEffect = finishedWork;
}
} else {
firstEffect = finishedWork.firstEffect;
}
}
flushPassiveEffects
先设置优先级然后调用flushPassiveEffectsImpl,执行所有effect的任务
function flushPassiveEffects() {
if (pendingPassiveEffectsRenderPriority !== NoSchedulerPriority) {
const priorityLevel =
pendingPassiveEffectsRenderPriority > NormalSchedulerPriority
? NormalSchedulerPriority
: pendingPassiveEffectsRenderPriority;
pendingPassiveEffectsRenderPriority = NoSchedulerPriority;
const previousLanePriority = getCurrentUpdateLanePriority();
try {
setCurrentUpdateLanePriority(
schedulerPriorityToLanePriority(priorityLevel),
);
return runWithPriority(priorityLevel, flushPassiveEffectsImpl);
} finally {
setCurrentUpdateLanePriority(previousLanePriority);
}
}
}
总结
- 这一章主要看了commitRootImpl函数部分代码
- 了解commmit阶段的前置工作
- 了解到有三个不一样的函数执行流程:
- before mutation 阶段(执行 DOM 操作前)
- mutation 阶段(执行 DOM 操作)
- layout 阶段(执行 DOM 操作后)
标签:前置,React,阶段,commit,firstEffect,null,root,finishedWork 来源: https://blog.csdn.net/schooling_chan/article/details/120925733