Heim  >  Artikel  >  Web-Frontend  >  Analyse der nextTick-Methode in Vue2.6

Analyse der nextTick-Methode in Vue2.6

不言
不言nach vorne
2019-02-28 11:58:152210Durchsuche

Der Inhalt dieses Artikels befasst sich mit der Analyse der nextTick-Methode in Vue2.6. Ich hoffe, dass er für Freunde in Not hilfreich ist.

Eine kurze Analyse der nextTick-Methode in Vue 2.6.

Ereignisschleife

JSs Ereignisschleife und Aufgabenwarteschlange sind tatsächlich der Schlüssel zum Verständnis des Konzepts von nextTick.
Es gibt tatsächlich viele hochwertige Artikel in diesem Internet, die es im Detail vorstellen, daher werde ich kurz darauf eingehen.

Der folgende Inhalt gilt für browserseitiges JS. Der Ereignisschleifenmechanismus von NodeJS ist anders. Die Spezifikation

sieht vor, dass Aufgaben in zwei Kategorien unterteilt werden: task(macrotask) und microtask.

Wird allgemein als Questquelle für task angesehen:

setTimeout / setInterval
setImmediate
MessageChannel
I/O
UI rendering

Wird allgemein als Questquelle für microtask angesehen:

Promise
process.nextTick
MutationObserver
Object.observe(已废弃)

Einfache Übersicht: (Hier sind (die offiziellen Spezifikationen)

  1. Erster StartAusführen des Skriptskripts, bis der Ausführungskontextstapel leer ist, dann mit dem Löschen der Aufgaben in der Mikrotask-Warteschlange. Die Warteschlange wird nach dem Prinzip „Wer zuerst kommt, mahlt zuerst“ bearbeitet. Führen Sie jedes einzelne aus, löschen Sie es und durchlaufen Sie die Ereignisschleife.

  2. Ereignisschleife: Rufen Sie kontinuierlich eine Aufgabe aus der Aufgabenwarteschlange ab, schieben Sie sie zur Ausführung auf den Stapel und führen Sie sie im Strom aus Schleife Löschen Sie die Aufgaben in der Mikrotask-Warteschlange nacheinander. Nach dem Löschen wird möglicherweise das Rendern der Seitenaktualisierung ausgelöst (bestimmt durch den Browser). Wiederholen Sie die Schritte Ereignisschleife

    nach
  3. .

nextTick

Das aktualisierte Rendern von Datenänderungen in Vue zu DOM ist ein asynchroner Prozess.

Diese Methode wird verwendet, um einen verzögerten Rückruf auszuführen, nachdem die DOM-Aktualisierungsschleife endet.
Die Verwendung ist ganz einfach:

// 修改数据
vm.msg = 'Hello';
// DOM 还没有更新
Vue.nextTick(function() {
  // DOM 更新了
});

// 作为一个 Promise 使用
Vue.nextTick().then(function() {
  // DOM 更新了
});
Der Quellcode, ohne Kommentare, hat tatsächlich nur weniger als hundert Zeilen und das Ganze ist trotzdem sehr leicht zu verstehen.

Dies ist in 3 Teile unterteilt.

Modulvariablen

Stellt eingeführte Module und definierte Variablen vor.

// noop 空函数,可用作函数占位符
import { noop } from 'shared/util';

// Vue 内部的错误处理函数
import { handleError } from './error';

// 判断是IE/IOS/内置函数
import { isIE, isIOS, isNative } from './env';

// 使用 MicroTask 的标识符
export let isUsingMicroTask = false;

// 以数组形式存储执行的函数
const callbacks = [];

// nextTick 执行状态
let pending = false;

// 遍历函数数组执行每一项函数
function flushCallbacks() {
  pending = false;
  const copies = callbacks.slice(0);
  callbacks.length = 0;
  for (let i = 0; i < copies.length; i++) {
    copies[i]();
  }
}

Asynchrone Verzögerungsfunktion

Als nächstes kommt die Kernfunktion

Asynchrone Verzögerungsfunktion. Die hier von den verschiedenen Vue-Versionen angewandten Strategien sind tatsächlich unterschiedlich.

2.6 Version bevorzugt die Verwendung von Microtask als asynchronen verzögerten Wrapper.

2.5 Version ist Makrotask kombiniert mit Mikrotask. Es gibt jedoch kleinere Probleme, wenn sich der Status vor dem Neuzeichnen ändert (z. B. #6813). Darüber hinaus kann die Verwendung von macrotask in einem Event-Handler zu seltsamem Verhalten führen, das nicht umgangen werden kann (wie #7109, #7153, #7546, #7834, #8109).

Also verwendet die

2.6-Version jetzt wieder Microtask Warum? . Weil 2.4 und frühere Versionen auch Microtask verwenden. . .

Microtask wird in einigen Fällen auch problematisch sein, da Microtask eine höhere Priorität hat und das Ereignis in der Reihenfolge der Ereignisse auftritt (z. B. #4521, # 6690) Problemumgehung) wird sogar während der Bubbling-Phase desselben Ereignisses ausgelöst (#6566).

// 核心的异步延迟函数,用于异步延迟调用 flushCallbacks 函数
let timerFunc;

// timerFunc 优先使用原生 Promise
// 原本 MutationObserver 支持更广,但在 iOS >= 9.3.3 的 UIWebView 中,触摸事件处理程序中触发会产生严重错误
if (typeof Promise !== 'undefined' && isNative(Promise)) {
  const p = Promise.resolve();
  timerFunc = () => {
    p.then(flushCallbacks);

    // IOS 的 UIWebView,Promise.then 回调被推入 microtask 队列但是队列可能不会如期执行。
    // 因此,添加一个空计时器“强制”执行 microtask 队列。
    if (isIOS) setTimeout(noop);
  };
  isUsingMicroTask = true;

  // 当原生 Promise 不可用时,timerFunc 使用原生 MutationObserver
  // 如 PhantomJS,iOS7,Android 4.4
  // issue #6466 MutationObserver 在 IE11 并不可靠,所以这里排除了 IE
} else if (
  !isIE &&
  typeof MutationObserver !== 'undefined' &&
  (isNative(MutationObserver) ||
    // PhantomJS 和 iOS 7.x
    MutationObserver.toString() === '[object MutationObserverConstructor]')
) {
  let counter = 1;
  const observer = new MutationObserver(flushCallbacks);
  const textNode = document.createTextNode(String(counter));
  observer.observe(textNode, {
    characterData: true,
  });
  timerFunc = () => {
    counter = (counter + 1) % 2;
    textNode.data = String(counter);
  };
  isUsingMicroTask = true;

  // 如果原生 setImmediate 可用,timerFunc 使用原生 setImmediate
} else if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) {
  timerFunc = () => {
    setImmediate(flushCallbacks);
  };
} else {
  // 最后的倔强,timerFunc 使用 setTimeout
  timerFunc = () => {
    setTimeout(flushCallbacks, 0);
  };
}
Zusammenfassung der Prioritäten in einem Satz:

Mikrotask-Priorität.
Promise > MutationObserver > setTimeoutnextTick-Funktion

nextTick-Funktion. Akzeptiert zwei Parameter:

    cb callback function
  1. : ist die zu verzögernde Funktion

  2. ctx
  3. : Geben Sie an, dass

    this der cb-Callback-Funktion auf Vue-Instanzmethode

    $nextTick
  4. zeigt, und
ctx

ist auf die aktuelle Vue-Instanz eingestellt.

export function nextTick(cb?: Function, ctx?: Object) {
  let _resolve;

  // cb 回调函数会经统一处理压入 callbacks 数组
  callbacks.push(() => {
    if (cb) {
      // 给 cb 回调函数执行加上了 try-catch 错误处理
      try {
        cb.call(ctx);
      } catch (e) {
        handleError(e, ctx, 'nextTick');
      }
    } else if (_resolve) {
      _resolve(ctx);
    }
  });

  // 执行异步延迟函数 timerFunc
  if (!pending) {
    pending = true;
    timerFunc();
  }

  // 当 nextTick 没有传入函数参数的时候,返回一个 Promise 化的调用
  if (!cb && typeof Promise !== 'undefined') {
    return new Promise(resolve => {
      _resolve = resolve;
    });
  }
}
Zusammenfassung

Als Ganzes betrachtet fühlt es sich relativ leicht zu verstehen an~ 2.6 Die Version ist etwas einfacher als zuvor.

Zusammenfassend lässt sich sagen, was jedes Mal getan wird, wenn aufgerufen wird:

cb-Funktion

wird verarbeitet und in das Vue.nextTick(cb)Callbacks-Array
verschoben, und das timerFunc-Funktion wird ausgeführt , verzögert den Aufruf der flushCallbacks-Funktion und durchläuft alle Funktionen im Callbacks-Array und führt sie aus. Die Priorität verzögerter Anrufe ist wie folgt: Promise

>

setImmediate
> 🎜>VersionsunterschiedeTatsächlich sind die nextTick-Strategien der

Vue 2.4, 2.5, 2.6

-Versionen geringfügig anders. Insgesamt sind

2,6

und 2,4 relativ ähnlich. (Schauen Sie genauer hin, es ist im Grunde dasselbe. 2.6 timerFunc verfügt über ein zusätzliches SetImmediate-Urteil)

2.5 Die Version ist tatsächlich ähnlich. . . Der Quellcode ist etwas anders geschrieben: Promise > MessageChannel > Das Update wird im v-on-Ereignishandler ausgelöst. NextTick verwendet zuerst die Makrotask.

Das obige ist der detaillierte Inhalt vonAnalyse der nextTick-Methode in Vue2.6. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:segmentfault.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen