当前位置:首页 > 科技  > 软件

一图看懂 React 源码中的同步更新逻辑

来源: 责编: 时间:2024-05-11 09:21:16 413观看
导读在 React 源码中,scheduleUpdateOnFiber 是所有任务的唯一入口方法。我们前面分析 useState 的实现原理章节中,我们可以清晰的知道,当我们调用 dispatchSetState 时,最终会调用该入口方法。scheduleUpdateOnFiber 主要用

vWu28资讯网——每日最新资讯28at.com

在 React 源码中,scheduleUpdateOnFiber 是所有任务的唯一入口方法。我们前面分析 useState 的实现原理章节中,我们可以清晰的知道,当我们调用 dispatchSetState 时,最终会调用该入口方法。vWu28资讯网——每日最新资讯28at.com

vWu28资讯网——每日最新资讯28at.com

scheduleUpdateOnFiber 主要用于触发一个 Fiber 节点上的调度更新任务,该函数里主要有两个核心逻辑。vWu28资讯网——每日最新资讯28at.com

// Mark that the root has a pending update.// 标记 root 上有一个更新任务markRootUpdated(root, lane, eventTime);ensureRootIsScheduled(root, eventTime);

markRootUpdated 的逻辑如下,简单了解一下即可。vWu28资讯网——每日最新资讯28at.com

export function markRootUpdated(  root: FiberRoot,  updateLane: Lane,  eventTime: number,) {  // 设置本次更新的优先级  root.pendingLanes |= updateLane;  // 重置 root 应用根节点的优先级  if (updateLane !== IdleLane) {      // 由 Suspence 而挂起的 update 对应的 lane 集合    root.suspendedLanes = NoLanes;     // 由请求成功,Suspence 取消挂起的 update 对应的 Lane 集合    root.pingedLanes = NoLanes;   }  const eventTimes = root.eventTimes;  const index = laneToIndex(updateLane);  eventTimes[index] = eventTime;}

ensureRootIsScheduled 的主要目的要确保 root 根节点被调度。在该逻辑中,会根据 root.pendingLanes 信息计算出本次更新的 Lanes: nextLanes。vWu28资讯网——每日最新资讯28at.com

const nextLanes = getNextLanes(  root,  root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes,);

然后根据 nextLanes 计算出本批次集合中优先级最高的 Lane,作为本地任务的优先级。vWu28资讯网——每日最新资讯28at.com

// We use the highest priority lane to represent the priority of the callback.const newCallbackPriority = getHighestPriorityLane(nextLanes);

后续的逻辑就是取出当前已存在的调度优先级,与 newCallbackPriority 进行对比,根据对比结果来执行不同的更新方法。当该值等于 SyncLane 时,表示为同步更新。vWu28资讯网——每日最新资讯28at.com

同步优先级例如点击事件。vWu28资讯网——每日最新资讯28at.com

然后会判断是否支持微任务更新,如果不支持最后会执行 scheduleCallback。vWu28资讯网——每日最新资讯28at.com

if (newCallbackPriority === SyncLane) {  if (supportsMicrotasks) {    // Flush the queue in a microtask.    if (__DEV__ && ReactCurrentActQueue.current !== null) {      // Inside `act`, use our internal `act` queue so that these get flushed      // at the end of the current scope even when using the sync version      // of `act`.      ReactCurrentActQueue.current.push(flushSyncCallbacks);    } else {      scheduleMicrotask(() => {        // In Safari, appending an iframe forces microtasks to run.        // https://github.com/facebook/react/issues/22459        // We don't support running callbacks in the middle of render        // or commit so we need to check against that.        if (          (executionContext & (RenderContext | CommitContext)) ===          NoContext        ) {          // Note that this would still prematurely flush the callbacks          // if this happens outside render or commit phase (e.g. in an event).          flushSyncCallbacks();        }      });    }  } else {    // Flush the queue in an Immediate task.    scheduleCallback(ImmediateSchedulerPriority, flushSyncCallbacks);  }}

scheduleSyncCallback 的逻辑,也就是同步任务的调度非常简单,就是将执行同步任务的回调添加到一个同步队列 syncQueue 中。vWu28资讯网——每日最新资讯28at.com

export function scheduleSyncCallback(callback: SchedulerCallback) {  // Push this callback into an internal queue. We'll flush these either in  // the next tick, or earlier if something calls `flushSyncCallbackQueue`.  if (syncQueue === null) {    syncQueue = [callback];  } else {    // Push onto existing queue. Don't need to schedule a callback because    // we already scheduled one when we created the queue.    syncQueue.push(callback);  }}

这里的 callback 是之前传入的 performSyncWorkOnRoot,这是用来执行同步更新任务的方法。他的逻辑主要包括:vWu28资讯网——每日最新资讯28at.com

  • 调用 renderRootSync,该方法会执行 workLoopSync,最后生成 Fiber true。
  • 将创建完成的 Fiber tree 挂载到 root 节点上。
  • 最后调用 commitRoot,进入 commit 阶段修改真实 DOM。
function performSyncWorkOnRoot(root) {  ...  let exitStatus = renderRootSync(root, lanes);    ...  root.finishedWork = finishedWork;  root.finishedLanes = lanes;  commitRoot(    root,    workInProgressRootRecoverableErrors,    workInProgressTransitions,  );  ensureRootIsScheduled(root, now());  return null;}

workLoopSync 的逻辑也非常简单,如下:vWu28资讯网——每日最新资讯28at.com

function workLoopSync() {  // Already timed out, so perform work without checking if we need to yield.  while (workInProgress !== null) {    performUnitOfWork(workInProgress);  }}

在 performUnitOfWork 中,会调用 beginWork 方法开始创建 Fiber 节点。vWu28资讯网——每日最新资讯28at.com

var next = beginWork(  current,   unitOfWork,   subtreeRenderLanes);

总结

同步更新的过程比较简单,从 scheduleUpdateOnFiber 到 beginWork 这中间的流程里,大多数逻辑都在进行各种不同情况的判断,因此源码看上去比较吃力,实际逻辑并不是很重要,简单了解即可,重要的是 beginWork 创建 Fiber 节点的方法,这跟我们之前文章里提到过的优化策略是一致的。vWu28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-87990-0.html一图看懂 React 源码中的同步更新逻辑

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 一篇学会Go中reflect反射的详细用法

下一篇: SpringBoot3使用虚拟线程一定要小心了

标签:
  • 热门焦点
  • 线程通讯的三种方法!通俗易懂

    线程通信是指多个线程之间通过某种机制进行协调和交互,例如,线程等待和通知机制就是线程通讯的主要手段之一。 在 Java 中,线程等待和通知的实现手段有以下几种方式:Object 类下
  • 摸鱼心法第一章——和配置文件说拜拜

    为了能摸鱼我们团队做了容器化,但是带来的问题是服务配置文件很麻烦,然后大家在群里进行了“亲切友好”的沟通图片图片图片图片对比就对比,简单对比下独立配置中心和k8s作为配
  • K8S | Service服务发现

    一、背景在微服务架构中,这里以开发环境「Dev」为基础来描述,在K8S集群中通常会开放:路由网关、注册中心、配置中心等相关服务,可以被集群外部访问;图片对于测试「Tes」环境或者
  • JavaScript学习 -AES加密算法

    引言在当今数字化时代,前端应用程序扮演着重要角色,用户的敏感数据经常在前端进行加密和解密操作。然而,这样的操作在网络传输和存储中可能会受到恶意攻击的威胁。为了确保数据
  • 梁柱接棒两年,腾讯音乐闯出新路子

    文丨田静 出品丨牛刀财经(niudaocaijing)7月5日,企鹅FM发布官方公告称由于业务调整,将于9月6日正式停止运营,这意味着腾讯音乐长音频业务走向消亡。腾讯在长音频领域还在摸索。为
  • 本地生活这块肥肉,拼多多也想吃一口

    出品/壹览商业 作者/李彦编辑/木鱼拼多多也看上本地生活这块蛋糕了。近期,拼多多在App首页“充值中心”入口上线了本机生活界面。壹览商业发现,该界面目前主要
  • 冯提莫签约抖音公会 前“斗鱼一姐”消失在直播间

    来源:直播观察提起“冯提莫”这个名字,很多网友或许听过,但应该不记得她是哪位主播了。其实,作为曾经的“斗鱼一姐”,冯提莫在游戏直播的年代影响力不输于现
  • 三星折叠屏手机去年销售近1000万台 今年目标定为1500万

    7月29日消息,三星率先发力可折叠手机市场,在全球市场已经取得了非常亮眼的成绩,接下来会进一步巩固和扩大这一优势。三星在推出Galaxy Z Flip5和Galax
  • 2021中国国际消费电子博览会与青岛国际软件融合创新博览会新闻发布会隆重举行

    9月18日,2021中国国际消费电子博览会与青岛国际软件融合创新博览会新闻发布会在青岛国际新闻中心隆重举行。发布会上青岛市政府领导联袂出席,对本次双展会情
Top