在React中,commitRoot是一个非常重要的函数,它主要进行以下操作:
- 首先,它会获取当前的更新队列,这是一个保存了所有需要更新的组件的队列。
- 然后,它会根据更新队列中每个组件的更新类型,将这些组件分成不同的列表。这些更新类型包括插入、更新和删除。
- 接下来,对于每个需要插入的组件,commitRoot会调用ReactDOM的createInstance函数来创建组件的实例,并将其插入到DOM中。
- 对于需要更新的组件,commitRoot会调用ReactDOM的updateInstance函数来更新组件的属性和状态,并更新DOM。
- 最后,对于需要删除的组件,commitRoot会调用ReactDOM的deleteInstance函数来删除组件的实例,并从DOM中移除对应的节点。
function commitRoot(root) {
const previousUpdatePriority = getCurrentUpdatePriority();
try {
//把当前的更新优先级设置为1
setCurrentUpdatePriority(DiscreteEventPriority);
commitRootImpl(root)
} finally {
setCurrentUpdatePriority(previousUpdatePriority);
}
}
function commitRootImpl(root) {
//先获取新的构建好的fiber树的根fiber tag=3
const { finishedWork } = root;
console.log('commit', finishedWork.child.memoizedState.memoizedState[0]);
workInProgressRoot = null;
workInProgressRootRenderLanes = NoLanes;
root.callbackNode = null;
root.callbackPriority = NoLane;
//合并统计当前新的根上剩下的车道
const remainingLanes = mergeLanes(finishedWork.lanes, finishedWork.childLanes);
markRootFinished(root, remainingLanes);
if ((finishedWork.subtreeFlags & Passive) !== NoFlags
|| (finishedWork.flags & Passive) !== NoFlags) {
if (!rootDoesHavePassiveEffect) {
rootDoesHavePassiveEffect = true;
Scheduler_scheduleCallback(NormalSchedulerPriority, flushPassiveEffect);
}
}
//判断子树有没有副作用
const subtreeHasEffects = (finishedWork.subtreeFlags & MutationMask) !== NoFlags;
const rootHasEffect = (finishedWork.flags & MutationMask) !== NoFlags;
//如果自己的副作用或者子节点有副作用就进行提交DOM操作
if (subtreeHasEffects || rootHasEffect) {
//当DOM执行变更之后
commitMutationEffectsOnFiber(finishedWork, root);
//执行layout Effect
commitLayoutEffects(finishedWork, root);
if (rootDoesHavePassiveEffect) {
rootDoesHavePassiveEffect = false;
rootWithPendingPassiveEffects = root;
}
}
//等DOM变更后,就可以把让root的current指向新的fiber树
root.current = finishedWork;
//在提交之后,因为根上可能会有跳过的更新,所以需要重新再次调度
ensureRootIsScheduled(root, now());
}
总之,commitRoot是React更新DOM的核心函数之一,它通过对更新队列中每个组件的更新类型进行分析,并调用相应的函数来完成DOM的更新和渲染。
此外,commitRoot函数还会触发一些React的生命周期方法,如componentDidMount、componentDidUpdate和componentWillUnmount等,以便在组件更新和渲染时执行一些必要的操作。
需要注意的是,commitRoot函数不是同步执行的,它会将所有的DOM更新操作都放在一个队列中进行异步更新,以便提高性能和减少页面的重绘次数。
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第7天,点击查看活动详情