Skip to content
On this page

在执行 FiberNodecompleteWork 之后,进入 commit 阶段,开始渲染

js
function performSyncWorkOnRoot() {
	//...
	const finishedWork = root.current.alternate;
  root.finishedWork = finishedWork;
  root.finishedLanes = lanes;
  commitRoot(root);
	ensureRootIsScheduled(root, now());
}

function commitRoot(root) {
  const renderPriorityLevel = getCurrentPriorityLevel(); // 调度优先级
  runWithPriority(
    ImmediateSchedulerPriority,
    commitRootImpl.bind(null, root, renderPriorityLevel),
  );
  // 最终调用 commitRootImpl
  return null;
}

function commitRootImpl(root, renderPriorityLevel) {
	do {
	// 执行在本次 commit 之前没有执行的 useEffect回调和其他同步任务
	// 由于这些任务回调可能触发新的渲染,因此使用循环
		flushPassiveEffects();
	} while(rootWithPendingPassiveEffects !== null);

	const finishedWork = root.finishedWork;
  // 凡是变量名带lane的都是优先级相关
  const lanes = root.finishedLanes;
  if (finishedWork === null) {
    return null;
  }
  root.finishedWork = null;
  root.finishedLanes = NoLanes;
  
  // 重置Scheduler绑定的回调函数
  root.callbackNode = null;
  root.callbackId = NoLanes;  
  // 清除已完成的discrete updates,例如:用户鼠标点击触发的更新。
  if (rootsWithPendingDiscreteUpdates !== null) {
    if (
      !hasDiscreteLanes(remainingLanes) &&
      rootsWithPendingDiscreteUpdates.has(root)
    ) {
      rootsWithPendingDiscreteUpdates.delete(root);
    }
  } 
  // 重置全局变量
  if (root === workInProgressRoot) {
    workInProgressRoot = null;
    workInProgress = null;
    workInProgressRootRenderLanes = NoLanes;
  }
  
  // 将effectList赋值给firstEffect
  // 由于每个fiber的effectList只包含他的子孙节点
  // 所以根节点如果有flags则不会被包含进来
  // 所以这里将有flags的根节点插入到effectList尾部
  // 这样才能保证有effect的fiber都在effectList中
	let firstEffect;
	if (finishedWork.flags > PerformedWork) {
		if (finishedWork.lastEffect !== null) {
			finishedWork.lastEffect.nextEffect = finishedWork;
			firstEffect = finishedWork.firstEffect;
		} else {
			firstEffect = finishedWork;
		}
	} else {
		// 根节点没有flags
		firstEffect = finishedWork.firstEffect;
	}

	//... before mutation阶段(执行`DOM`操作前)
	nextEffect = firstEffect;
	do{
		commitBeforeMutationEffects()
	} while(nextEffect !== null);
	
	// mutation阶段(执行`DOM`操作)
	nextEffect = firstEffect;
	do{
		commitMutationEffects()
	} while(nextEffect !== null);
	
	// layout阶段(执行`DOM`操作后)
	nextEffect = firstEffect;
	do{
		commitLayoutEffects()
	} while(nextEffect !== null);

	// ... 最后调度root,由于commit阶段可能产生新的更新
	ensureRootIsScheduled(root, now());

	
	// 执行同步任务,这样同步任务不需要等到下次事件循环再执行
	// 比如在 componentDidMount 中执行 setState 创建的更新会在这里被同步执行
	// 或useLayoutEffect
	flushSyncCallbackQueue();
	return null
}