react源码解析10.commit阶段
视频讲解(高效学习):进入学习
往期文章:
在render阶段的末尾会调用commitRoot(root);进入commit阶段,这里的root指的就是fiberRoot,然后会遍历render阶段生成的effectList,effectList上的Fiber节点保存着对应的props变化。之后会遍历effectList进行对应的dom操作和生命周期、hooks回调或销毁函数,各个函数做的事情如下
在commitRoot函数中其实是调度了commitRootImpl函数
//ReactFiberWorkLoop.old.js
function commitRoot(root) {
var renderPriorityLevel = getCurrentPriorityLevel();
runWithPriority$1(ImmediatePriority$1, commitRootImpl.bind(null, root, renderPriorityLevel));
return null;
}
在commitRootImpl的函数中主要分三个部分:
-
commit阶段前置工作
-
调用flushPassiveEffects执行完所有effect的任务
-
初始化相关变量
-
赋值firstEffect给后面遍历effectList用
//ReactFiberWorkLoop.old.js do { // 调用flushPassiveEffects执行完所有effect的任务 flushPassiveEffects(); } while (rootWithPendingPassiveEffects !== null); //... // 重置变量 finishedWork指rooFiber root.finishedWork = null; //重置优先级 root.finishedLanes = NoLanes; // Scheduler回调函数重置 root.callbackNode = null; root.callbackId = NoLanes; // 重置全局变量 if (root === workInProgressRoot) { workInProgressRoot = null; workInProgress = null; workInProgressRootRenderLanes = NoLanes; } else { } //rootFiber可能会有新的副作用 将它也加入到effectLis let firstEffect; if (finishedWork.effectTag > PerformedWork) { if (finishedWork.lastEffect !== null) { finishedWork.lastEffect.nextEffect = finishedWork; firstEffect = finishedWork.firstEffect; } else { firstEffect = finishedWork; } } else { firstEffect = finishedWork.firstEffect; }
-
-
mutation阶段
遍历effectList分别执行三个方法commitBeforeMutationEffects、commitMutationEffects、commitLayoutEffects执行对应的dom操作和生命周期
在介绍双缓存Fiber树的时候,我们在构建完workInProgress Fiber树之后会将fiberRoot的current指向workInProgress Fiber,让workInProgress Fiber成为current,这个步骤发生在commitMutationEffects函数执行之后,commitLayoutEffects之前,因为componentWillUnmount发生在commitMutationEffects函数中,这时还可以获取之前的Update,而componentDidMount
和
componentDidUpdate会在commitLayoutEffects中执行,这时已经可以获取更新后的真实dom了function commitRootImpl(root, renderPriorityLevel) { //... do { //... commitBeforeMutationEffects(); } while (nextEffect !== null); do { //... commitMutationEffects(root, renderPriorityLevel);//commitMutationEffects } while (nextEffect !== null); root.current = finishedWork;//切换current Fiber树 do { //... commitLayoutEffects(root, lanes);//commitLayoutEffects } while (nextEffect