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)
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.
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.
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 更新了 });
// 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. 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 die2.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); }; }
Mikrotask-Priorität.
Promise > MutationObserver > setTimeoutnextTick-Funktion
nextTick-Funktion. Akzeptiert zwei Parameter:
this der cb-Callback-Funktion auf Vue-Instanzmethode
$nextTick 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;
});
}
}
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
-Versionen geringfügig anders. Insgesamt sind
2,6und 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!