成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

一圖看懂 React 源碼中的同步更新邏輯

開發 前端
同步更新的過程比較簡單,從 ScheduleUpdateOnFiber 到 BeginWork 這中間的流程里,大多數邏輯都在進行各種不同情況的判斷,因此源碼看上去比較吃力,實際邏輯并不是很重要,簡單了解即可。

在 React 源碼中,scheduleUpdateOnFiber 是所有任務的唯一入口方法。我們前面分析 useState 的實現原理章節中,我們可以清晰的知道,當我們調用 dispatchSetState 時,最終會調用該入口方法。

scheduleUpdateOnFiber 主要用于觸發一個 Fiber 節點上的調度更新任務,該函數里主要有兩個核心邏輯。

// Mark that the root has a pending update.
// 標記 root 上有一個更新任務
markRootUpdated(root, lane, eventTime);

ensureRootIsScheduled(root, eventTime);

markRootUpdated 的邏輯如下,簡單了解一下即可。

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。

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

然后根據 nextLanes 計算出本批次集合中優先級最高的 Lane,作為本地任務的優先級。

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

后續的邏輯就是取出當前已存在的調度優先級,與 newCallbackPriority 進行對比,根據對比結果來執行不同的更新方法。當該值等于 SyncLane 時,表示為同步更新。

同步優先級例如點擊事件。

然后會判斷是否支持微任務更新,如果不支持最后會執行 scheduleCallback。

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 中。

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,這是用來執行同步更新任務的方法。他的邏輯主要包括:

  • 調用 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 的邏輯也非常簡單,如下:

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

在 performUnitOfWork 中,會調用 beginWork 方法開始創建 Fiber 節點。

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

總結

同步更新的過程比較簡單,從 scheduleUpdateOnFiber 到 beginWork 這中間的流程里,大多數邏輯都在進行各種不同情況的判斷,因此源碼看上去比較吃力,實際邏輯并不是很重要,簡單了解即可,重要的是 beginWork 創建 Fiber 節點的方法,這跟我們之前文章里提到過的優化策略是一致的。

責任編輯:姜華 來源: 這波能反殺
相關推薦

2017-04-12 11:15:52

ReactsetState策略

2023-11-28 09:44:10

2023-11-01 09:00:14

存儲Docker服務器

2023-04-07 08:02:54

源碼位邏輯運算符

2020-05-20 14:25:45

Reactreact.js前端

2021-01-01 09:04:44

Linux內核變量

2019-06-26 19:18:05

Windows 10系統更新微軟

2025-01-20 09:15:00

iOS 18.3蘋果iOS 18

2023-05-17 19:30:52

企業

2015-03-10 10:15:27

AppleWatch開發Swift

2024-02-19 14:58:34

編程范式開發

2024-01-24 09:14:27

編程范式數據

2024-02-21 14:06:00

Linux文件系統

2021-10-11 09:41:20

React位運算技巧前端

2019-11-24 19:17:06

MySQL異步復制全同步復制

2021-04-26 09:22:07

ASP.NET Cor服務周期

2024-07-16 14:52:31

擴展系統負載均衡器

2019-03-18 15:00:48

SQLJoin用法數據庫

2020-10-21 08:38:47

React源碼

2018-05-18 18:09:44

人工智能
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 啪啪免费| 日韩在线免费视频 | 亚洲国产小视频 | 欧美色综合天天久久综合精品 | 国产精品国产成人国产三级 | 精品国偷自产在线 | 天天色天天 | 成人在线播放 | 欧美一区二区网站 | 天天射美女 | 久久国产精品99久久久大便 | 亚洲免费网 | 一级欧美一级日韩片 | 国产成人免费视频网站视频社区 | 精品一二区 | 365夜爽爽欧美性午夜免费视频 | 日韩精品av一区二区三区 | 久久久久免费精品国产小说色大师 | 国产激情片在线观看 | 99热精品在线 | 国产一区二区精品在线 | 欧美毛片免费观看 | 亚洲天堂av在线 | 黄色国产大片 | 日本成人中文字幕在线观看 | 99久久久无码国产精品 | 天天摸天天干 | 精品久久久久久亚洲精品 | 麻豆一区一区三区四区 | 久久精品一区二区 | 人人澡人人爱 | 国产一区二区精品 | 99精品久久久久久中文字幕 | 日韩欧美专区 | 久久99精品久久久久久秒播九色 | 国产精品日韩在线观看 | 91久久精品国产 | 国产一区二区三区久久久久久久久 | 一区二区三区 在线 | av一级毛片 | 国产精品99久久久久久人 |