Skip to content
目录

commitRoot

在RenderRoot阶段,Fiber树已经构建好了,并且在更新阶段,需要插入、删除、更新的DOM节点的effectTag都标记在了Fiber节点上;

在CommitRoot阶段,就是来处理这些具体的操作;在Concurrent Mode下,具有一些高优先级的任务也是在这个阶段被处理;

  1. reconciler阶段,针对有副作用的节点,将当前的具有副作用的Fiber添加到FirstEffect->LastEffect链上
  2. completeUnitOfWork阶段,将FirstEffect->LastEffect依次往父节点上移动并连接
  3. renderRoot阶段结束后,将当前处理的Fiber(RootFiber)alternate指针赋值给FiberRoot的finishedWork
typescript
function onComplete(
  root: FiberRoot,
  finishedWork: Fiber,
  expirationTime: ExpirationTime,
) {
  root.pendingCommitExpirationTime = expirationTime;
  // finishedWork 赋值 
  root.finishedWork = finishedWork;
}
// root.current.alternate 其实就是RootFiber在运行中更新的那个副本 
const rootWorkInProgress = root.current.alternate;
onComplete(root, rootWorkInProgress, expirationTime);

总结

在整个commitRoot阶段都是围绕着finishedWork进行遍历处理

做了什么?

  • 提交Snapshot
  • 提交HostComponent的 side effect, 渲染到页面上
  • 提交所有组件的生命周期

伪代码实现

commitRoot代码比较长,这里只看重要的部分,首先,在内部是循环finishedWork.firstEffect链,一共有三次循环。那么每次循环都做了什么呢?

  1. 第一个循环: 主要处理了Snapshot相关的事情,比如class组件的getSnapshotBeforeUpdate方法的调用
  2. 第二个循环: 将dom节点进行插入、更新、删除、然后append到container中;
  3. 第三个循环: 调用class组件相关的声明周期,函数组件的useLayoutEffect声明周期、以及useLayoutEffect和useEffect的卸载函数;
  4. 循环走完后,会将useEffect使用Scheduler根据优先级调度,也就是进行(Concurrent Mode下)异步更新
typescript
function commitRoot(root: FiberRoot, finishedWork: Fiber): void {
  isWorking = true;
  isCommitting = true;
  let nextEffect
  let firstEffect = finishedWork.firstEffect;
  nextEffect = firstEffect;
  // 对一个循环
  while (nextEffect !== null) {
    let didError = false;
    let error;
    try {
      commitBeforeMutationLifecycles();
    } catch (e) {
      didError = true;
    }
  }
  
  nextEffect = firstEffect;
  // 第二个循环
  while (nextEffect !== null) {
    let didError = false;
    let error;
    try {
      commitAllHostEffects();
    } catch (e) {
      didError = true;
      error = e;
    }
  }
  nextEffect = firstEffect;
  // 第三个循环
  while (nextEffect !== null) {
    let didError = false;
    let error;
    try {
      commitAllLifeCycles(root, committedExpirationTime);
    } catch (e) {
      didError = true;
      error = e;
    }
  }
  if (firstEffect !== null && rootWithPendingPassiveEffects !== null) {
    // 这个时候调用useEffect,先调用unmount, 在调用 mount ,这个时候已经渲染完成了
    // 不会阻塞渲染
    let callback = commitPassiveEffects.bind(null, root, firstEffect);
    passiveEffectCallbackHandle = runWithPriority(NormalPriority, () => {
      return schedulePassiveEffects(callback);
    });
    passiveEffectCallback = callback;
  }
  isCommitting = false;
  isWorking = false;
  onCommitRoot(finishedWork.stateNode);
}

具体操作

备案号: 浙ICP备2023000081号