国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

React16.2的fiber架構(2)

Caicloud / 1054人閱讀

摘要:為了幫助理解,我們繼續加日志司徒正美,加群一起研究與只要收到更新對象,就會被調度程序調用。渲染器在將來的某個時刻調用。導步肯定為歡迎加繼續略也是怒長,代碼的特點是許多巨型類,巨型方法,有之遺風。

insertUpdateIntoFiber 會根據fiber的狀態創建一個或兩個列隊對象,對象是長成這樣的

//by 司徒正美, 加群:370262116 一起研究React與anujs
// https://github.com/RubyLouvre/anu 歡迎加star
function createUpdateQueue(baseState) {//我們現在是丟了一個null做傳參
  var queue = {
    baseState: baseState,
    expirationTime: NoWork,//NoWork會被立即執行
    first: null,
    last: null,
    callbackList: null,
    hasForceUpdate: false,
    isInitialized: false
  };

  return queue;
}

scheduleWork是一個奇怪的方法,只是添加一下參數

 function scheduleWork(fiber, expirationTime) {
    return scheduleWorkImpl(fiber, expirationTime, false);
  }

scheduleWorkImpl的最開頭有一個recordScheduleUpdate方法,用來記錄調度器的執行狀態,如注釋所示,它現在相當于什么都沒有做

function recordScheduleUpdate() {
  if (enableUserTimingAPI) {//全局變量,默認為true
    if (isCommitting) {//全局變量,默認為false, 沒有進入分支
      hasScheduledUpdateInCurrentCommit = true;
    }
    //全局變量,默認為null,沒有沒有進入分支
    if (currentPhase !== null && currentPhase !== "componentWillMount" && currentPhase !== "componentWillReceiveProps") {
      hasScheduledUpdateInCurrentPhase = true;
    }
  }
}

scheduleWorkImpl的一些分支非常復雜,我們打一些斷點

function computeExpirationForFiber(fiber) {
    var expirationTime = void 0;
    if (expirationContext !== NoWork) {
      // An explicit expiration context was set;
      expirationTime = expirationContext;
    } else if (isWorking) {
      if (isCommitting) {
        // Updates that occur during the commit phase should have sync priority
        // by default.
        expirationTime = Sync;
      } else {
        // Updates during the render phase should expire at the same time as
        // the work that is being rendered.
        expirationTime = nextRenderExpirationTime;
      }
    } else {
      // No explicit expiration context was set, and we"re not currently
      // performing work. Calculate a new expiration time.
      if (useSyncScheduling && !(fiber.internalContextTag & AsyncUpdates)) {
        // This is a sync update
        console.log("expirationTime", Sync)
        expirationTime = Sync;//命中這里
      } else {
        // This is an async update
        expirationTime = computeAsyncExpiration();
      }
    }
    return expirationTime;
  }
    function checkRootNeedsClearing(root, fiber, expirationTime) {
    if (!isWorking && root === nextRoot && expirationTime < nextRenderExpirationTime) {
      console.log("checkRootNeedsClearing對nextRoot,nextUnitOfWork,nextRenderExpirationTime進行置空")
      // Restart the root from the top.
      if (nextUnitOfWork !== null) {
        // This is an interruption. (Used for performance tracking.)
        interruptedBy = fiber;
      }
      nextRoot = null;
      nextUnitOfWork = null;
      nextRenderExpirationTime = NoWork;
    }else{
      console.log("checkRootNeedsClearing就是想醬油")
    }
  }

function scheduleWorkImpl(fiber, expirationTime, isErrorRecovery) {
    recordScheduleUpdate();//現在什么也沒做

    var node = fiber;
    while (node !== null) {
      // Walk the parent path to the root and update each node"s
      // expiration time.
      if (node.expirationTime === NoWork || node.expirationTime > expirationTime) {
        node.expirationTime = expirationTime;//由于默認就是NoWork,因此會被重寫 Sync
      }
      if (node.alternate !== null) {//這里進不去
        if (node.alternate.expirationTime === NoWork || node.alternate.expirationTime > expirationTime) {
          node.alternate.expirationTime = expirationTime;
        }
      }
      if (node["return"] === null) {
        if (node.tag === HostRoot) {//進入這里
          var root = node.stateNode;
          checkRootNeedsClearing(root, fiber, expirationTime);
          console.log("requestWork",root, expirationTime)
          requestWork(root, expirationTime);
          checkRootNeedsClearing(root, fiber, expirationTime);
        } else {
          return;
        }
      }
      node = node["return"];
    }
  }

輸出如下

requestWork也很難理解,里面太多全局變量,覺得不是前端的人搞的。為了幫助理解,我們繼續加日志

//by 司徒正美, 加群:370262116 一起研究React與anujs

 // requestWork is called by the scheduler whenever a root receives an update.
  // It"s up to the renderer to call renderRoot at some point in the future.
  /*
只要root收到更新(update對象),requestWork就會被調度程序調用。
渲染器在將來的某個時刻調用renderRoot。
  */
  function requestWork(root, expirationTime) {
    if (nestedUpdateCount > NESTED_UPDATE_LIMIT) {
      invariant_1(false, "Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.");
    }

    // Add the root to the schedule.
    // Check if this root is already part of the schedule.
    if (root.nextScheduledRoot === null) {
      // This root is not already scheduled. Add it.
      console.log("設置remainingExpirationTime",expirationTime)
      root.remainingExpirationTime = expirationTime;
      if (lastScheduledRoot === null) {
        console.log("設置firstScheduledRoot, lastScheduledRoot")
        firstScheduledRoot = lastScheduledRoot = root;
        root.nextScheduledRoot = root;
      } else {
        lastScheduledRoot.nextScheduledRoot = root;
        lastScheduledRoot = root;
        lastScheduledRoot.nextScheduledRoot = firstScheduledRoot;
      }
    } else {
      // This root is already scheduled, but its priority may have increased.
      var remainingExpirationTime = root.remainingExpirationTime;
      if (remainingExpirationTime === NoWork || expirationTime < remainingExpirationTime) {
        // Update the priority.
        root.remainingExpirationTime = expirationTime;
      }
    }

    if (isRendering) {
      // Prevent reentrancy. Remaining work will be scheduled at the end of
      // the currently rendering batch.
      return;
    }

    if (isBatchingUpdates) {
      // Flush work at the end of the batch.
      if (isUnbatchingUpdates) {
        // ...unless we"re inside unbatchedUpdates, in which case we should
        // flush it now.
        nextFlushedRoot = root;
        nextFlushedExpirationTime = Sync;
        console.log("performWorkOnRoot")
        performWorkOnRoot(nextFlushedRoot, nextFlushedExpirationTime);
      }
      return;
    }

    // TODO: Get rid of Sync and use current time?
    if (expirationTime === Sync) {
      console.log("進入performWork")
      performWork(Sync, null);
    } else {
      scheduleCallbackWithExpiration(expirationTime);
    }
  }

從日志輸出來看,requestWork只是修改了兩個全局變量,然后進入performWork。這三個內部方法起名很有意思。scheduleWork意為打算工作,requestWork意為申請工作,performWork意為努力工作(正式上班)

function performWork(minExpirationTime, dl) {
    deadline = dl;

    // Keep working on roots until there"s no more work, or until the we reach
    // the deadline.
    //這里會將root設置為highestPriorityRoot
    findHighestPriorityRoot();

    if (enableUserTimingAPI && deadline !== null) {
      var didExpire = nextFlushedExpirationTime < recalculateCurrentTime();
      console.log(didExpire)
      stopRequestCallbackTimer(didExpire);
    }

    while (nextFlushedRoot !== null 
      && nextFlushedExpirationTime !== NoWork 
      && (minExpirationTime === NoWork || nextFlushedExpirationTime <= minExpirationTime) 
      && !deadlineDidExpire) {
      console.log("performWorkOnRoot")
      performWorkOnRoot(highestPriorityRoot, nextFlushedExpirationTime);
      // Find the next highest priority work.
      findHighestPriorityRoot();
    }

    // We"re done flushing work. Either we ran out of time in this callback,
    // or there"s no more work left with sufficient priority.

    // If we"re inside a callback, set this to false since we just completed it.
    if (deadline !== null) {
      callbackExpirationTime = NoWork;
      callbackID = -1;
    }
    // If there"s work left over, schedule a new callback.
    if (nextFlushedExpirationTime !== NoWork) {
      console.log("scheduleCallbackWithExpiration")
      scheduleCallbackWithExpiration(nextFlushedExpirationTime);
    }

    // Clean-up.
    deadline = null;
    deadlineDidExpire = false;
    nestedUpdateCount = 0;

    if (hasUnhandledError) { //如果有沒處理的錯誤則throw
      var _error4 = unhandledError;
      unhandledError = null;
      hasUnhandledError = false;
      throw _error4;
    }
  }

我們終于進入performWorkOnRoot,performWorkOnRoot的作用是區分同步渲染還是異步渲染,expirationTime等于1,因此進入同步。導步肯定為false

// https://github.com/RubyLouvre/anu 歡迎加star

function performWorkOnRoot(root, expirationTime) {

    isRendering = true;

    // Check if this is async work or sync/expired work.
    // TODO: Pass current time as argument to renderRoot, commitRoot
    if (expirationTime <= recalculateCurrentTime()) {
      // Flush sync work.
     
      var finishedWork = root.finishedWork;
      console.log("Flush sync work.", finishedWork)
      if (finishedWork !== null) {
        // This root is already complete. We can commit it.
        root.finishedWork = null;
        console.log("commitRoot")
        root.remainingExpirationTime = commitRoot(finishedWork);
      } else {
        root.finishedWork = null;
        console.log("renderRoot")
        finishedWork = renderRoot(root, expirationTime);
        if (finishedWork !== null) {
          console.log("繼續commitRoot")
          // We"ve completed the root. Commit it.
          root.remainingExpirationTime = commitRoot(finishedWork);
        }
      }
    } else {
      console.log("Flush async work.")
      // Flush async work.
      // ...略
    }

    isRendering = false;
  }

renderRoot也是怒長,React16代碼的特點是許多巨型類,巨型方法,有JAVA之遺風。renderRoot只有前面幾行是可能處理虛擬DOM(或叫fiber),后面都是錯誤邊界的

function renderRoot(root, expirationTime) {
   
    isWorking = true;

    // We"re about to mutate the work-in-progress tree. If the root was pending
    // commit, it no longer is: we"ll need to complete it again.
    root.isReadyForCommit = false;

    // Check if we"re starting from a fresh stack, or if we"re resuming from
    // previously yielded work.
    if (root !== nextRoot || expirationTime !== nextRenderExpirationTime || nextUnitOfWork === null) {
      // Reset the stack and start working from the root.
      resetContextStack();
      nextRoot = root;
      nextRenderExpirationTime = expirationTime;
      //可能是用來工作的代碼
       console.log("createWorkInProgress")
      nextUnitOfWork = createWorkInProgress(nextRoot.current, null, expirationTime);
    }
    //可能是用來工作的代碼
     console.log("startWorkLoopTimer")
    startWorkLoopTimer(nextUnitOfWork);
   // 處理錯誤邊界
    var didError = false;
    var error = null;
    invokeGuardedCallback$1(null, workLoop, null, expirationTime);
    // An error was thrown during the render phase.
    while (didError) {
       console.log("componentDidCatch的相關實現")
      if (didFatal) {
        // This was a fatal error. Don"t attempt to recover from it.
        firstUncaughtError = error;
        break;
      }

      var failedWork = nextUnitOfWork;
      if (failedWork === null) {
        // An error was thrown but there"s no current unit of work. This can
        // happen during the commit phase if there"s a bug in the renderer.
        didFatal = true;
        continue;
      }

      // 處理錯誤邊界
      var boundary = captureError(failedWork, error);
      !(boundary !== null) ? invariant_1(false, "Should have found an error boundary. This error is likely caused by a bug in React. Please file an issue.") : void 0;

      if (didFatal) {
        // The error we just captured was a fatal error. This happens
        // when the error propagates to the root more than once.
        continue;
      }
       // 處理錯誤邊界
      didError = false;
      error = null;
      // We"re finished working. Exit the error loop.
      break;
    }
   // 處理錯誤邊界
    var uncaughtError = firstUncaughtError;

    // We"re done performing work. Time to clean up.
    stopWorkLoopTimer(interruptedBy);
    interruptedBy = null;
    isWorking = false;
    didFatal = false;
    firstUncaughtError = null;
     // 處理錯誤邊界
    if (uncaughtError !== null) {
      onUncaughtError(uncaughtError);
    }

    return root.isReadyForCommit ? root.current.alternate : null;
  }

  function resetContextStack() {
    // Reset the stack
    reset$1();
    // Reset the cursors
    resetContext();
    resetHostContainer();
  }

function reset$1() {
  console.log("reset",index)
  while (index > -1) {
    valueStack[index] = null;

    {
      fiberStack[index] = null;
    }

    index--;
  }
}

function resetContext() {
  consoel.log("resetContext")
  previousContext = emptyObject_1;
  contextStackCursor.current = emptyObject_1;
  didPerformWorkStackCursor.current = false;
}

  function resetHostContainer() {
    console.log("resetHostContainer",contextStackCursor, rootInstanceStackCursor, NO_CONTEXT )
    contextStackCursor.current = NO_CONTEXT;
    rootInstanceStackCursor.current = NO_CONTEXT;
  }

createWorkInProgress就是將根組件的fiber對象再復制一份,變成其alternate屬性。因此 將虛擬DOM轉換為真實DOM的重任就交給invokeGuardedCallback

var invokeGuardedCallback = function (name, func, context, a, b, c, d, e, f) {
  ReactErrorUtils._hasCaughtError = false;
  ReactErrorUtils._caughtError = null;
  var funcArgs = Array.prototype.slice.call(arguments, 3);
  try {
    func.apply(context, funcArgs);
  } catch (error) {
    ReactErrorUtils._caughtError = error;
    ReactErrorUtils._hasCaughtError = true;
  }
//這下面還有怒長(100-150L )的關于錯誤邊界的處理,略過
};

func為workLoop

//by 司徒正美, 加群:370262116 一起研究React與anujs

 function workLoop(expirationTime) {
    if (capturedErrors !== null) {
      // If there are unhandled errors, switch to the slow work loop.
      // TODO: How to avoid this check in the fast path? Maybe the renderer
      // could keep track of which roots have unhandled errors and call a
      // forked version of renderRoot.
      slowWorkLoopThatChecksForFailedWork(expirationTime);
      return;
    }
    if (nextRenderExpirationTime === NoWork || nextRenderExpirationTime > expirationTime) {
      return;
    }

    if (nextRenderExpirationTime <= mostRecentCurrentTime) {
      // Flush all expired work.
      while (nextUnitOfWork !== null) {
        console.log("performUnitOfWork",nextUnitOfWork)
        nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
      }
    } else {
      // Flush asynchronous work until the deadline runs out of time.
      while (nextUnitOfWork !== null && !shouldYield()) {
        nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
      }
    }
  }


我們終于看到工作的代碼了。 這個nextUnitOfWork 是renderRoot生成的
performUnitOfWork與beginWork的代碼,里面會根據fiber的tag進入各種操作

//by 司徒正美, 加群:370262116 一起研究React與anujs
// https://github.com/RubyLouvre/anu 歡迎加star

function performUnitOfWork(workInProgress) {
    // The current, flushed, state of this fiber is the alternate.
    // Ideally nothing should rely on this, but relying on it here
    // means that we don"t need an additional field on the work in
    // progress.
    var current = workInProgress.alternate;

    // See if beginning this work spawns more work.
    startWorkTimer(workInProgress);
    {
      ReactDebugCurrentFiber.setCurrentFiber(workInProgress);
    }
    console.log("beginWork")
    var next = beginWork(current, workInProgress, nextRenderExpirationTime);
    {
      ReactDebugCurrentFiber.resetCurrentFiber();
    }
    if (true && ReactFiberInstrumentation_1.debugTool) {
      ReactFiberInstrumentation_1.debugTool.onBeginWork(workInProgress);
    }

    if (next === null) {
      console.log("next")
      // If this doesn"t spawn new work, complete the current work.
      next = completeUnitOfWork(workInProgress);
    }

    ReactCurrentOwner.current = null;

    return next;
  }
function beginWork(current, workInProgress, renderExpirationTime) {
    if (workInProgress.expirationTime === NoWork || workInProgress.expirationTime > renderExpirationTime) {
      return bailoutOnLowPriority(current, workInProgress);
    }

    switch (workInProgress.tag) {
      case IndeterminateComponent:
        return mountIndeterminateComponent(current, workInProgress, renderExpirationTime);
      case FunctionalComponent:
        return updateFunctionalComponent(current, workInProgress);
      case ClassComponent:
        return updateClassComponent(current, workInProgress, renderExpirationTime);
      case HostRoot:
        return updateHostRoot(current, workInProgress, renderExpirationTime);
      case HostComponent:
        return updateHostComponent(current, workInProgress, renderExpirationTime);
      case HostText:
        return updateHostText(current, workInProgress);
      case CallHandlerPhase:
        // This is a restart. Reset the tag to the initial phase.
        workInProgress.tag = CallComponent;
      // Intentionally fall through since this is now the same.
      case CallComponent:
        return updateCallComponent(current, workInProgress, renderExpirationTime);
      case ReturnComponent:
        // A return component is just a placeholder, we can just run through the
        // next one immediately.
        return null;
      case HostPortal:
        return updatePortalComponent(current, workInProgress, renderExpirationTime);
      case Fragment:
        return updateFragment(current, workInProgress);
      default:
        invariant_1(false, "Unknown unit of work tag. This error is likely caused by a bug in React. Please file an issue.");
    }
  }

我們再調查一下workInProgress.tag是什么

https://github.com/facebook/r...

這里有全部fiber節點的類型描述,我們創建一個對象

// https://github.com/RubyLouvre/anu 歡迎加star

var mapBeginWork = {
    3: "HostRoot 根組件",
    0: "IndeterminateComponent 只知道type為函數",
    2: "ClassComponent 普通類組件" ,
    5: "HostComponent 元素節點",
    6: "HostText 文本節點"
  }
  function beginWork(current, workInProgress, renderExpirationTime) {
    if (workInProgress.expirationTime === NoWork || workInProgress.expirationTime > renderExpirationTime) {
      return bailoutOnLowPriority(current, workInProgress);
    }
    console.log(workInProgress.tag, mapBeginWork[workInProgress.tag])
     switch (workInProgress.tag) {
     //略
     }
}

總結一下到現在的所有流程:

好了,今天就這么多,想必大家都累了,下一篇繼續

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/107182.html

相關文章

  • React16.2fiber架構

    摘要:司徒正美,加群一起研究與用于調整渲染順序,高優先級的組件先執行這只是一部分更新邏輯,簡直沒完沒了,下次繼續添上流程圖,回憶一下本文學到的東西 React16真是一天一改,如果現在不看,以后也很難看懂了。 在React16中,雖然也是通過JSX編譯得到一個虛擬DOM對象,但對這些虛擬DOM對象的再加工則是經過翻天覆地的變化。我們需要追根溯底,看它是怎么一步步轉換過來的。我們先不看什么組件...

    lansheng228 評論0 收藏0
  • 精讀《React16 新特性》

    摘要:引言于發布版本,時至今日已更新到,且引入了大量的令人振奮的新特性,本文章將帶領大家根據更新的時間脈絡了解的新特性。其作用是根據傳遞的來更新。新增等指針事件。 1 引言 于 2017.09.26 Facebook 發布 React v16.0 版本,時至今日已更新到 React v16.6,且引入了大量的令人振奮的新特性,本文章將帶領大家根據 React 更新的時間脈絡了解 React1...

    Nosee 評論0 收藏0
  • 淺談React Fiber

    摘要:因為版本將真正廢棄這三生命周期到目前為止,的渲染機制遵循同步渲染首次渲染,更新時更新時卸載時期間每個周期函數各司其職,輸入輸出都是可預測,一路下來很順暢。通過進一步觀察可以發現,預廢棄的三個生命周期函數都發生在虛擬的構建期間,也就是之前。 showImg(https://segmentfault.com/img/bVbweoj?w=559&h=300); 背景 前段時間準備前端招聘事項...

    izhuhaodev 評論0 收藏0
  • React Fiber 架構理解

    摘要:架構理解引用原文是核心算法正在進行的重新實現。構建的過程就是的過程,通過來調度執行一組任務,每完成一個任務后回來看看有沒有插隊的更緊急的,把時間控制權交還給主線程,直到下一次回調再繼續構建。 React Fiber 架構理解 引用原文:React Fiber ArchitectureReact Fiber is an ongoing reimplementation of Reacts...

    Berwin 評論0 收藏0

發表評論

0條評論

Caicloud

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<