この記事の内容は Vue2.6 の nextTick メソッドの解析に関するものです。必要な方は参考にしていただければ幸いです。
Vue 2.6 の nextTick メソッドの簡単な分析。
イベント ループ
JS の イベント ループ と タスク キュー は、実際、nextTick の概念を理解するための鍵です。
実際、このインターネット上にはそれを詳しく紹介した質の高い記事がたくさんあるので、簡単に読んでみました。
次の内容はブラウザ側 JS に適用されます。NodeJS のイベント ループ メカニズムは異なります。
仕様では、タスクが task(macrotask)
と microtask
の 2 つのカテゴリに分類されると規定されています。
通常 task
と見なされるタスク ソース:
setTimeout / setInterval setImmediate MessageChannel I/O UI rendering
通常 microtask
と見なされるタスク ソース:
Promise process.nextTick MutationObserver Object.observe(已废弃)
簡単な概要: (これが公式の仕様です)
まず、実行コンテキスト スタックが空になるまで スクリプト script の実行を開始し、その後 ## のクリアを開始します。 #microtask queue タスクは先入れ先出しでキューに入れられ、それぞれが次々に実行され、タスクがクリアされた後にイベント ループが実行されます。
イベント ループ: タスク キューからタスクを継続的にフェッチし、実行のためにスタックにプッシュし、現在のタスクで実行します。ループ microtask queue 内のタスクを順番にクリアします。クリア後、ページ更新のレンダリングがトリガーされる場合があります (ブラウザーによって決定されます)。
イベント ループの手順を繰り返します。
nextTick
Vue のデータから DOM の更新されたレンダリングへの変更は、非同期プロセスです。このメソッドは、DOM 更新サイクルの終了後に遅延コールバックを実行するために使用されます。
使用方法は非常に簡単です:
// 修改数据 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](); } }
非同期遅延関数です。ここで、Vue のバージョンごとに採用される戦略は実際には異なります。
2.6 バージョンでは、microtask を非同期遅延ラッパーとして使用することを優先します。
2.5 バージョンは、macrotask と microtask を組み合わせたものです。ただし、再描画前に状態が変化する場合 (#6813 など)、小さな問題が発生します。さらに、イベント ハンドラーで macrotask を使用すると、回避できない奇妙な動作が発生する可能性があります (#7109、#7153、#7546、#7834、#8109 など)。
つまり、2.6 バージョンは現在 microtask を使用していますが、これもなぜでしょうか。 。 2.4 以前のバージョンでも microtask を使用しているためです。 。 。
microtask microtask の優先順位が高く、イベントが一連のイベントで発生するため、場合によっては問題が発生します (#4521、 #6690 回避策) 同じイベントのバブリング中にも起動します (#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); }; }
マイクロタスクの優先度。
約束 > MutationObserver > setImmediate > setTimeoutnextTick関数
nextTick 関数。 2 つのパラメータを受け入れます:
this は を指します。
$nextTick がさらにカプセル化され、 ctx は 現在の Vue インスタンス
に設定されます。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; }); } }
まとめ全体的に見ると、比較的わかりやすいと思います~ 2.6 このバージョンは、以前よりも少しシンプルになっています。
要約すると、Vue.nextTick(cb) が呼び出されるたびに何が行われるかになります。
cb 関数が処理され、 にプッシュされます。 callbacks array、
timerFunc 関数 を実行し、flushCallbacks 関数
の呼び出しを遅らせ、
callbacks 配列 内のすべての関数を走査して実行します。 遅延呼び出しの優先順位は次のとおりです: Promise > setImmediate >
実際、Vue 2.4、2.5、および 2.6 バージョンの nextTick 戦略は次のとおりです。若干異なります。 全体的に 2.6
2.4 は比較的似ています。 (よく見てください。基本的には同じです。2.6
timerFunc には setImmediate の判定が追加されています)2.5 バージョンは実際には似ています。 。 。ソース コードの書き方は少し異なります。 Promise > setTimeout >更新は v-on イベント ハンドラーでトリガーされ、nextTick は最初にマクロタスクを使用します。
以上がVue2.6のnextTickメソッドの解析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。