Heim Web-Frontend js-Tutorial Detaillierte Erläuterung der Faserarchitektur von React16.2

Detaillierte Erläuterung der Faserarchitektur von React16.2

Feb 03, 2018 pm 02:23 PM
fiber 详解

本文主要和大家分享React16.2的fiber架构详解,希望能帮助到大家。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;
}
Nach dem Login kopieren

scheduleWork是一个奇怪的方法,只是添加一下参数

 function scheduleWork(fiber, expirationTime) {
    return scheduleWorkImpl(fiber, expirationTime, false);
  }
Nach dem Login kopieren

scheduleWorkImpl的最开头有一个recordScheduleUpdate方法,用来记录调度器的执行状态,如注释所示,它现在相当于什么都没有做

function recordScheduleUpdate() {
  if (enableUserTimingAPI) {//全局变量,默认为true
    if (isCommitting) {//全局变量,默认为false, 没有进入分支
      hasScheduledUpdateInCurrentCommit = true;
    }
    //全局变量,默认为null,没有没有进入分支
    if (currentPhase !== null && currentPhase !== 'componentWillMount' && currentPhase !== 'componentWillReceiveProps') {
      hasScheduledUpdateInCurrentPhase = true;
    }
  }
}
Nach dem Login kopieren

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&#39;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'];
    }
  }
Nach dem Login kopieren

输出如下

Detaillierte Erläuterung der Faserarchitektur von React16.2

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&#39;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);
    }
  }
Nach dem Login kopieren

从日志输出来看,requestWork只是修改了两个全局变量,然后进入performWork。这三个内部方法起名很有意思。scheduleWork意为打算工作,requestWork意为申请工作,performWork意为努力工作(正式上班)

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

    // Keep working on roots until there&#39;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&#39;re done flushing work. Either we ran out of time in this callback,
    // or there&#39;s no more work left with sufficient priority.

    // If we&#39;re inside a callback, set this to false since we just completed it.
    if (deadline !== null) {
      callbackExpirationTime = NoWork;
      callbackID = -1;
    }
    // If there&#39;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;
    }
  }
Nach dem Login kopieren

Detaillierte Erläuterung der Faserarchitektur von React16.2

我们终于进入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&#39;ve completed the root. Commit it.
          root.remainingExpirationTime = commitRoot(finishedWork);
        }
      }
    } else {
      console.log("Flush async work.")
      // Flush async work.
      // ...略
    }

    isRendering = false;
  }
Nach dem Login kopieren

Detaillierte Erläuterung der Faserarchitektur von React16.2

renderRoot也是怒长,React16代码的特点是许多巨型类,巨型方法,有JAVA之遗风。renderRoot只有前面几行是可能处理虚拟DOM(或叫fiber),后面都是错误边界的

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

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

    // Check if we&#39;re starting from a fresh stack, or if we&#39;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&#39;t attempt to recover from it.
        firstUncaughtError = error;
        break;
      }

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

      // 处理错误边界
      var boundary = captureError(failedWork, error);
      !(boundary !== null) ? invariant_1(false, &#39;Should have found an error boundary. This error is likely caused by a bug in React. Please file an issue.&#39;) : 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&#39;re finished working. Exit the error loop.
      break;
    }
   // 处理错误边界
    var uncaughtError = firstUncaughtError;

    // We&#39;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;
  }
Nach dem Login kopieren

Detaillierte Erläuterung der Faserarchitektur von React16.2

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 )的关于错误边界的处理,略过
};
Nach dem Login kopieren

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);
      }
    }
  }
Nach dem Login kopieren

Detaillierte Erläuterung der Faserarchitektur von React16.2
我们终于看到工作的代码了。 这个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&#39;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&#39;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.');
    }
  }
Nach dem Login kopieren

我们再调查一下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) {
     //略
     }
}
Nach dem Login kopieren

Detaillierte Erläuterung der Faserarchitektur von React16.2

相关推荐:

nodejs中的fiber(纤程)库详解_node.js


Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung der Faserarchitektur von React16.2. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

AI Hentai Generator

AI Hentai Generator

Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

R.E.P.O. Energiekristalle erklärten und was sie tun (gelber Kristall)
4 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Beste grafische Einstellungen
4 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. So reparieren Sie Audio, wenn Sie niemanden hören können
4 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: Wie man alles in Myrise freischaltet
1 Monate vor By 尊渡假赌尊渡假赌尊渡假赌

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Detaillierte Erläuterung der Modusfunktion in C++ Detaillierte Erläuterung der Modusfunktion in C++ Nov 18, 2023 pm 03:08 PM

Detaillierte Erläuterung der Modusfunktion in C++ In der Statistik bezieht sich der Modus auf den Wert, der in einem Datensatz am häufigsten vorkommt. In der Sprache C++ können wir den Modus in jedem Datensatz finden, indem wir eine Modusfunktion schreiben. Die Modusfunktion kann auf viele verschiedene Arten implementiert werden. Zwei der häufig verwendeten Methoden werden im Folgenden ausführlich vorgestellt. Die erste Methode besteht darin, eine Hash-Tabelle zu verwenden, um die Häufigkeit des Vorkommens jeder Zahl zu zählen. Zuerst müssen wir eine Hash-Tabelle definieren, in der jede Zahl der Schlüssel und die Häufigkeit des Vorkommens der Wert ist. Dann führen wir für einen bestimmten Datensatz aus

Ausführliche Erklärung zur Erlangung von Administratorrechten in Win11 Ausführliche Erklärung zur Erlangung von Administratorrechten in Win11 Mar 08, 2024 pm 03:06 PM

Das Windows-Betriebssystem ist eines der beliebtesten Betriebssysteme der Welt und seine neue Version Win11 hat viel Aufmerksamkeit erregt. Im Win11-System ist die Erlangung von Administratorrechten ein wichtiger Vorgang. Mit Administratorrechten können Benutzer weitere Vorgänge und Einstellungen auf dem System durchführen. In diesem Artikel wird ausführlich beschrieben, wie Sie Administratorrechte im Win11-System erhalten und wie Sie Berechtigungen effektiv verwalten. Im Win11-System werden Administratorrechte in zwei Typen unterteilt: lokaler Administrator und Domänenadministrator. Ein lokaler Administrator verfügt über vollständige Administratorrechte für den lokalen Computer

Detaillierte Erläuterung der Divisionsoperation in Oracle SQL Detaillierte Erläuterung der Divisionsoperation in Oracle SQL Mar 10, 2024 am 09:51 AM

Detaillierte Erläuterung der Divisionsoperation in OracleSQL In OracleSQL ist die Divisionsoperation eine häufige und wichtige mathematische Operation, die zur Berechnung des Ergebnisses der Division zweier Zahlen verwendet wird. Division wird häufig in Datenbankabfragen verwendet. Daher ist das Verständnis der Divisionsoperation und ihrer Verwendung in OracleSQL eine der wesentlichen Fähigkeiten für Datenbankentwickler. In diesem Artikel werden die relevanten Kenntnisse über Divisionsoperationen in OracleSQL ausführlich erörtert und spezifische Codebeispiele als Referenz für die Leser bereitgestellt. 1. Divisionsoperation in OracleSQL

Detaillierte Erläuterung der Restfunktion in C++ Detaillierte Erläuterung der Restfunktion in C++ Nov 18, 2023 pm 02:41 PM

Detaillierte Erläuterung der Restfunktion in C++ In C++ wird der Restoperator (%) verwendet, um den Rest der Division zweier Zahlen zu berechnen. Es handelt sich um einen binären Operator, dessen Operanden ein beliebiger Ganzzahltyp (einschließlich char, short, int, long usw.) oder ein Gleitkommazahlentyp (z. B. float, double) sein kann. Der Restoperator gibt ein Ergebnis mit demselben Vorzeichen wie der Dividend zurück. Für die Restoperation von Ganzzahlen können wir beispielsweise den folgenden Code zur Implementierung verwenden: inta=10;intb=3;

Detaillierte Erläuterung der Verwendung der Vue.nextTick-Funktion und ihrer Anwendung bei asynchronen Updates Detaillierte Erläuterung der Verwendung der Vue.nextTick-Funktion und ihrer Anwendung bei asynchronen Updates Jul 26, 2023 am 08:57 AM

Detaillierte Erläuterung der Verwendung der Vue.nextTick-Funktion und ihrer Anwendung bei asynchronen Aktualisierungen. Bei der Vue-Entwicklung treten häufig Situationen auf, in denen Daten asynchron aktualisiert werden müssen. Beispielsweise müssen Daten sofort nach einer Änderung des DOM oder verwandter Vorgänge aktualisiert werden unmittelbar nach der Aktualisierung der Daten durchzuführen. Die von Vue bereitgestellte Funktion .nextTick wurde entwickelt, um diese Art von Problem zu lösen. In diesem Artikel wird die Verwendung der Vue.nextTick-Funktion im Detail vorgestellt und mit Codebeispielen kombiniert, um ihre Anwendung bei asynchronen Updates zu veranschaulichen. 1. Vue.nex

Detaillierte Erläuterung der PHP-FPM-Optimierungsmethode Detaillierte Erläuterung der PHP-FPM-Optimierungsmethode Jul 08, 2023 pm 04:31 PM

PHP-FPM ist ein häufig verwendeter PHP-Prozessmanager, der eine bessere PHP-Leistung und -Stabilität bietet. In einer Hochlastumgebung erfüllt die Standardkonfiguration von PHP-FPM jedoch möglicherweise nicht die Anforderungen, sodass wir sie optimieren müssen. In diesem Artikel wird die Optimierungsmethode von PHP-FPM ausführlich vorgestellt und einige Codebeispiele gegeben. 1. Erhöhen Sie die Anzahl der Prozesse. Standardmäßig startet PHP-FPM nur eine kleine Anzahl von Prozessen, um Anfragen zu bearbeiten. In einer Hochlastumgebung können wir die Parallelität von PHP-FPM erhöhen, indem wir die Anzahl der Prozesse erhöhen.

Detaillierte Erläuterung der Rolle und Verwendung des PHP-Modulo-Operators Detaillierte Erläuterung der Rolle und Verwendung des PHP-Modulo-Operators Mar 19, 2024 pm 04:33 PM

Der Modulo-Operator (%) in PHP wird verwendet, um den Rest der Division zweier Zahlen zu ermitteln. In diesem Artikel werden wir die Rolle und Verwendung des Modulo-Operators im Detail besprechen und spezifische Codebeispiele bereitstellen, um den Lesern ein besseres Verständnis zu erleichtern. 1. Die Rolle des Modulo-Operators Wenn wir in der Mathematik eine ganze Zahl durch eine andere ganze Zahl dividieren, erhalten wir einen Quotienten und einen Rest. Wenn wir beispielsweise 10 durch 3 dividieren, ist der Quotient 3 und der Rest ist 1. Um diesen Rest zu ermitteln, wird der Modulo-Operator verwendet. 2. Verwendung des Modulo-Operators In PHP verwenden Sie das %-Symbol, um den Modul darzustellen

Detaillierte Erläuterung der Funktion system() des Linux-Systemaufrufs Detaillierte Erläuterung der Funktion system() des Linux-Systemaufrufs Feb 22, 2024 pm 08:21 PM

Detaillierte Erläuterung der Funktion system() des Linux-Systems Der Systemaufruf ist ein sehr wichtiger Teil des Linux-Betriebssystems. Er bietet eine Möglichkeit, mit dem Systemkernel zu interagieren. Unter diesen ist die Funktion system() eine der am häufigsten verwendeten Systemaufruffunktionen. In diesem Artikel wird die Verwendung der Funktion system() ausführlich vorgestellt und entsprechende Codebeispiele bereitgestellt. Grundlegende Konzepte von Systemaufrufen Systemaufrufe sind eine Möglichkeit für Benutzerprogramme, mit dem Betriebssystemkernel zu interagieren. Benutzerprogramme fordern das Betriebssystem an, indem sie Systemaufruffunktionen aufrufen

See all articles