AVt天堂网 手机版,亚洲va久久久噜噜噜久久4399,天天综合亚洲色在线精品,亚洲一级Av无码毛片久久精品

當(dāng)前位置:首頁(yè) > 科技  > 軟件

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

來源: 責(zé)編: 時(shí)間:2024-05-11 09:21:16 269觀看
導(dǎo)讀在 React 源碼中,scheduleUpdateOnFiber 是所有任務(wù)的唯一入口方法。我們前面分析 useState 的實(shí)現(xiàn)原理章節(jié)中,我們可以清晰的知道,當(dāng)我們調(diào)用 dispatchSetState 時(shí),最終會(huì)調(diào)用該入口方法。scheduleUpdateOnFiber 主要用

RO928資訊網(wǎng)——每日最新資訊28at.com

在 React 源碼中,scheduleUpdateOnFiber 是所有任務(wù)的唯一入口方法。我們前面分析 useState 的實(shí)現(xiàn)原理章節(jié)中,我們可以清晰的知道,當(dāng)我們調(diào)用 dispatchSetState 時(shí),最終會(huì)調(diào)用該入口方法。RO928資訊網(wǎng)——每日最新資訊28at.com

RO928資訊網(wǎng)——每日最新資訊28at.com

scheduleUpdateOnFiber 主要用于觸發(fā)一個(gè) Fiber 節(jié)點(diǎn)上的調(diào)度更新任務(wù),該函數(shù)里主要有兩個(gè)核心邏輯。RO928資訊網(wǎng)——每日最新資訊28at.com

// Mark that the root has a pending update.// 標(biāo)記 root 上有一個(gè)更新任務(wù)markRootUpdated(root, lane, eventTime);ensureRootIsScheduled(root, eventTime);

markRootUpdated 的邏輯如下,簡(jiǎn)單了解一下即可。RO928資訊網(wǎng)——每日最新資訊28at.com

export function markRootUpdated(  root: FiberRoot,  updateLane: Lane,  eventTime: number,) {  // 設(shè)置本次更新的優(yōu)先級(jí)  root.pendingLanes |= updateLane;  // 重置 root 應(yīng)用根節(jié)點(diǎn)的優(yōu)先級(jí)  if (updateLane !== IdleLane) {      // 由 Suspence 而掛起的 update 對(duì)應(yīng)的 lane 集合    root.suspendedLanes = NoLanes;     // 由請(qǐng)求成功,Suspence 取消掛起的 update 對(duì)應(yīng)的 Lane 集合    root.pingedLanes = NoLanes;   }  const eventTimes = root.eventTimes;  const index = laneToIndex(updateLane);  eventTimes[index] = eventTime;}

ensureRootIsScheduled 的主要目的要確保 root 根節(jié)點(diǎn)被調(diào)度。在該邏輯中,會(huì)根據(jù) root.pendingLanes 信息計(jì)算出本次更新的 Lanes: nextLanes。RO928資訊網(wǎng)——每日最新資訊28at.com

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

然后根據(jù) nextLanes 計(jì)算出本批次集合中優(yōu)先級(jí)最高的 Lane,作為本地任務(wù)的優(yōu)先級(jí)。RO928資訊網(wǎng)——每日最新資訊28at.com

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

后續(xù)的邏輯就是取出當(dāng)前已存在的調(diào)度優(yōu)先級(jí),與 newCallbackPriority 進(jìn)行對(duì)比,根據(jù)對(duì)比結(jié)果來執(zhí)行不同的更新方法。當(dāng)該值等于 SyncLane 時(shí),表示為同步更新。RO928資訊網(wǎng)——每日最新資訊28at.com

同步優(yōu)先級(jí)例如點(diǎn)擊事件。RO928資訊網(wǎng)——每日最新資訊28at.com

然后會(huì)判斷是否支持微任務(wù)更新,如果不支持最后會(huì)執(zhí)行 scheduleCallback。RO928資訊網(wǎng)——每日最新資訊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 的邏輯,也就是同步任務(wù)的調(diào)度非常簡(jiǎn)單,就是將執(zhí)行同步任務(wù)的回調(diào)添加到一個(gè)同步隊(duì)列 syncQueue 中。RO928資訊網(wǎng)——每日最新資訊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,這是用來執(zhí)行同步更新任務(wù)的方法。他的邏輯主要包括:RO928資訊網(wǎng)——每日最新資訊28at.com

  • 調(diào)用 renderRootSync,該方法會(huì)執(zhí)行 workLoopSync,最后生成 Fiber true。
  • 將創(chuàng)建完成的 Fiber tree 掛載到 root 節(jié)點(diǎn)上。
  • 最后調(diào)用 commitRoot,進(jìn)入 commit 階段修改真實(shí) 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 的邏輯也非常簡(jiǎn)單,如下:RO928資訊網(wǎng)——每日最新資訊28at.com

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

在 performUnitOfWork 中,會(huì)調(diào)用 beginWork 方法開始創(chuàng)建 Fiber 節(jié)點(diǎn)。RO928資訊網(wǎng)——每日最新資訊28at.com

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

總結(jié)

同步更新的過程比較簡(jiǎn)單,從 scheduleUpdateOnFiber 到 beginWork 這中間的流程里,大多數(shù)邏輯都在進(jìn)行各種不同情況的判斷,因此源碼看上去比較吃力,實(shí)際邏輯并不是很重要,簡(jiǎn)單了解即可,重要的是 beginWork 創(chuàng)建 Fiber 節(jié)點(diǎn)的方法,這跟我們之前文章里提到過的優(yōu)化策略是一致的。RO928資訊網(wǎng)——每日最新資訊28at.com

本文鏈接:http://www.tebozhan.com/showinfo-26-87990-0.html一圖看懂 React 源碼中的同步更新邏輯

聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com

上一篇: 一篇學(xué)會(huì)Go中reflect反射的詳細(xì)用法

下一篇: SpringBoot3使用虛擬線程一定要小心了

標(biāo)簽:
  • 熱門焦點(diǎn)
Top