React commit阶段解析-前置学习

在renderRootSync执行完render相关阶段后,就会进入commit阶段。performSyncWorkOnRoot函数执行的末尾调用commitRoot(root);

commit阶段工作

在 rootFiber.firstEffect 上保存了一条需要执行副作用的 Fiber 节点的单向链表effectList,这些 Fiber 节点的 updateQueue 中保存了变化的 props。

这些副作用对应的 DOM 操作在commit 阶段执行。

除此之外,一些生命周期钩子(比如 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);
    }
  }
}

总结

  1. 这一章主要看了commitRootImpl函数部分代码
  2. 了解commmit阶段的前置工作
  3. 了解到有三个不一样的函数执行流程:
    • before mutation 阶段(执行 DOM 操作前)
    • mutation 阶段(执行 DOM 操作)
    • layout 阶段(执行 DOM 操作后)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值