# React源码解析之Reconciler运行循环与scheduler调度

React源码之看完吊打面试官系列

经历一个月的学习整理,站在前人的肩膀上,对React有了一些浅薄的理解,希望记录自己的学习过程的同时也可以给大家带来一点小帮助。如果此系列文章对您有些帮助,还望在座各位义夫义母不吝点赞关注支持🐶,也希望各位大佬拍砖探讨


本系列行文思路如下,本篇属于React中的React的管理员(reconciler与scheduler)

  • [X] React启动过程
  • [X] React的两大工作循环
  • [X] React中的对象
  • [ ] React fiber的初次创建与更新
  • [ ] React fiber的渲染
  • [X] React的管理员(reconciler与scheduler)
  • [X] react的优先级管理(Lane模型)

「React Hook原理」

  • [ ] 状态与副作用
  • [ ] Hook原理
  • [ ] 状态Hook
  • [ ] 副作用Hook

「其他」

  • [ ] React的合成事件
  • [ ] Context原理
  • [ ] diff算法

「React源码解析之Reconciler运行循环」

Reconciler运行循环概览

alt

reconciler包的主要作用,将主要功能分为4个方面:

  1. 「输入」:暴露api函数(如:scheduleUpdateOnFiber),提供给其他包(如react包)调用.(所有的输入的必经之路)
  2. 「注册调度任务」:与调度中心(scheduler包)交互,注册调度任务task,等待任务回调.
  3. 「执行任务回调」:在内存中构造出fiber树,同时与渲染器(react-dom)交互,在内存中创建出与fiber对应的DOM节点.
  4. 「输出」: 与渲染器(react-dom)交互,渲染DOM节点

输入

ReactFiberWorkLoop.js中, 承接输入的函数只有 scheduleUpdateOnFiberreact-reconciler对外暴露的 api 函数中, 只要涉及到需要改变 fiber 的操作(无论是首次渲染或后续更新操作), 最后都会间接调用 scheduleUpdateOnFiber, 所以 scheduleUpdateOnFiber函数是「输入链路中的必经之路」.

// 唯一接收输入信号的函数
export function scheduleUpdateOnFiber(
  fiber: Fiber,
  lane: Lane,
  eventTime: number,
{
  // ... 省略部分无关代码
  //给fiber节点添加优先级
  const root = markUpdateLaneFromFiberToRoot(fiber, lane);
  if (lane === SyncLane) {
    if (
      (executionContext & LegacyUnbatchedContext) !== NoContext &&
      (executionContext & (RenderContext | CommitContext)) === NoContext
    ) {
      // 直接进行`fiber构造`
      // 条件是NoContext,一般是初次构造,不经过调度
      performSyncWorkOnRoot(root);
    } else {
      // 注册调度任务, 经过`Scheduler`包的调度, 间接进行`fiber构造`
      ensureRootIsScheduled(root, eventTime);
    }
  } else {
    // 注册调度任务, 经过`Scheduler`包的调度, 间接进行`fiber构造`
    // 如果同步优先级,走'Scheduler'调度
    ensureRootIsScheduled(root, eventTime);
  }
}

注册调度任务

与输入环节紧密相连, scheduleUpdateOnFiber函数之后, 立即进入 ensureRootIsScheduled()函数

// ... 省略部分无关代码
function ensureRootIsScheduled(root: FiberRoot, currentTime: number{
  // 前半部分: 判断是否需要注册新的调度,(如果当前任务已经被挂起则不需要注册新的调度)
  const existingCallbackNode = root.callbackNode;
  const nextLanes = getNextLanes(
    root,
    root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes,
  );
  const newCallbackPriority = returnNextLanesPriority();
  if (nextLanes === NoLanes) {
    return;
  }
  if (existingCallbackNode !== null) {
    const existingCallbackPriority = root.callbackPriority;
    if (existingCallbackPriority === newCallbackPriority) {
      return;
    }
    cancelCallback(existingCallbackNode);
  }

  // 后半部分: 注册调度任务
  //其实是在scheduleCallback去创建task,然后加入任务队列里面,后面有详细解释
  let newCallbackNode;
  if (newCallbackPriority === SyncLanePriority) {
    newCallbackNode = scheduleSyncCallback(
      performSyncWorkOnRoot.bind(null, root),
    );
  } else if (newCallbackPriority === SyncBatchedLanePriority) {
    newCallbackNode = scheduleCallback(
      ImmediateSchedulerPriority,
      performSyncWorkOnRoot.bind(null, root),
    );
  } else {
    // concurrent模式下注册任务,然后加入任务队列
    const schedulerPriorityLevel = lanePriorityToSchedulerPriority(
      newCallbackPriority,
    );
    newCallbackNode = scheduleCallback(
      schedulerPriorityLevel,
      performConcurrentWorkOnRoot.bind(null, root),
    );
  }
  root.callbackPriority = newCallbackPriority;
  root.callbackNode = newCallbackNode;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值