Vue の DOM の非同期更新の簡単な分析

Vue の DOM の非同期更新の簡単な分析

データ オブジェクト: vue の data メソッドによって返されるオブジェクト。

Dep オブジェクト: 各データ属性は、このデータを使用するすべての Watcher オブジェクトを収集するための Dep を作成します。

ウォッチャーオブジェクト: 主にDOMのレンダリングに使用されます

Vue が DOM を非同期更新する原理

Vue でのデータ更新は非同期であるため、データを変更した後、変更された DOM 要素をすぐに取得することはできません。

1 実際の DOM 要素を取得できるのはいつですか?

Vue の nextTick コールバック内。

2 Vue は最新の DOM を取得するために nextTick メソッドを使用する必要があるのはなぜですか?

2.1 vue が Watcher を呼び出してビューを更新する場合、直接更新するのではなく、更新する必要がある Watcher を Queue キューに追加し、特定の更新メソッド flushSchedulerQueue を nexTick に渡して呼び出します。

// src > core > observer > watcher.js + scheduler.js // データが更新されると、次のコードが順番に実行されます // 1. Data.set をトリガーします
// 2. dep.notifyを呼び出す
// 3. Dep は関連するすべての Watcher を走査し、更新メソッドを実行します。class Watcher {
  // 4. 更新操作を実行する update() {
    キューウォッチャー(これ);
  }
}

定数キュー = [];

関数queueWatcher(ウォッチャー: ウォッチャー) {
  // 5. 現在の Watcher を非同期キューに追加します。queue.push(watcher);
  // 6. 非同期キューを実行し、コールバック nextTick(flushSchedulerQueue); を渡します。
}

// ビューを更新するための特定のメソッド function flushSchedulerQueue() {
  ウォッチャー、ID;
  // ソートし、最初に親ノードをレンダリングしてから、子ノードをレンダリングします。 // これにより、次のような不要な子ノードのレンダリングを回避できます。親ノードで v-if が false である子ノードはレンダリングする必要がありません。 queue.sort((a, b) => a.id - b.id);
  // バッチ更新のためにすべてのウォッチャーを走査します。
  (インデックス = 0; インデックス < キューの長さ; インデックス++) {
    ウォッチャー = キュー[インデックス];
    // DOMを更新する
    ウォッチャーを実行します。
  }
} 

2.2 nextTick -- 渡された flushSchedulerQueue をコールバック配列に追加し、timerFunc メソッドを実行します。

const コールバック = [];
timerFunc を作成します。

関数 nextTick(cb?: 関数、ctx?: オブジェクト) {
  _resolve を実行します。
  // 1. 渡されたflushSchedulerQueueメソッドをコールバック配列に追加します callbacks.push(() => {
    cb.call(ctx);
  });
  // 2. 非同期タスクを実行する // このメソッドは、ブラウザの互換性に応じて異なる非同期戦略 timerFunc() を選択します。
}

2.3 timerFunc メソッド - ブラウザの互換性に基づいて作成された非同期メソッドです。このメソッドを実行すると、flushSchedulerQueue メソッドが呼び出され、特定の DOM 更新が実行されます。

timerFunc を作成します。
// Promiseと互換性があるかどうかを判定する
if (typeof Promise !== "undefined") {
  タイマー関数 = () => {
    Promise.resolve() を実行してから (コールバックをフラッシュします);
  };
  // MutationObserverと互換性があるかどうかを判定する
  // https://developer.mozilla.org/zh-CN/docs/Web/API/MutationObserver
} そうでない場合 (typeof MutationObserver !== "undefined") {
  カウンターを1にします。
  const オブザーバー = 新しい MutationObserver(flushCallbacks);
  定数textNode = document.createTextNode(String(counter));
  オブザーバー.observe(textNode, {
    文字データ: true、
  });
  タイマー関数 = () => {
    カウンター = (カウンター + 1) % 2;
    textNode.data = String(カウンター);
  };
  // setImmediateと互換性があるかどうかを判定する
  // このメソッドは一部の IE ブラウザに存在します} else if (typeof setImmediate !== "undefined") {
  // これはマクロタスクですが、setTimeout よりも優れています timerFunc = () => {
    即時設定(コールバックをフラッシュ)。
  };
} それ以外 {
  // 上記の方法がわからない場合は、setTimeout 0 を使用します
  タイマー関数 = () => {
    タイムアウトを設定します(コールバックをフラッシュします、0);
  };
}

// 非同期実行後、すべてのコールバックメソッドを実行します。つまり、flushSchedulerQueueを実行します。
関数flushCallbacks() {
  (i = 0 とします; i < コピー数.長さ; i++) {
    コールバック[i]();
  }
} 

2.4 論理的判断力を向上させる

2.4.1 同じウォッチャーをキューに追加しないように、has フラグを決定します。

2.4.2 待機フラグを決定し、1ティック以内にすべてのウォッチャーを更新します。

2.4.3 フラッシュ フラグを決定し、Watcher がレンダリングされるときに生成される可能性のある新しい Watcher を処理します。

v-if 条件がトリガーされると、新しく追加された Watcher がレンダリングされます。

ヒント: nextTick は、Promise、setTimeout、その他のメソッドによってシミュレートされる単なる非同期タスクです。

3 なぜ this.$nextTick は更新された DOM を取得できるのでしょうか?

this.$nextTick を呼び出すと、実際には図の nextTick メソッドが呼び出され、非同期キュー内のコールバック関数が実行されます。先入先出の原則に従って、データの変更によってトリガーされた更新非同期キューが最初に実行されます。実行が完了すると、新しい DOM が生成されます。次に this.$nextTick のコールバック関数が実行されると、更新された DOM 要素を取得できます。

// this.$nextTick を使用して nextTick メソッドを呼び出します Vue.prototype.$nextTick = function (fn: Function) {
  nextTick(fn, this) を返します。
};

要約: Vue 非同期更新の原則

Vue のデータが変更されると、このデータに関連するすべてのウォッチャーが更新をトリガーされます。まず、すべてのウォッチャーがキューに追加されます。次に、nextTick メソッドを呼び出して非同期タスクを実行します。非同期タスクのコールバックでは、キュー内のウォッチャーをソートし、対応する DOM 更新を実行します。

Vue の DOM 非同期更新の実装に関するこの記事はこれで終わりです。Vue の DOM 非同期更新に関するより関連性の高いコンテンツについては、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • VUE は DOM を非同期的に更新します - $nextTick を使用して DOM ビューの問題を解決します
  • Vue.js ソースコードからの非同期 DOM 更新戦略と nextTick の詳細な説明
  • Vue バッチ更新 DOM 実装手順

<<:  MySQLは「order by」がどのように機能するかを簡単に理解します

>>:  NextCloud プライベート クラウド ストレージ ネットワーク ディスクの構築に関する詳細なチュートリアル

推薦する

CSS 擬似要素::マーカーの詳細な説明

この記事では、CSS ::markerの興味深い疑似要素を紹介します。これを使用すると、テキスト番号...

Linuxで相対パスを表現する方法

たとえば、現在のパスが /var/log で、/usr ディレクトリに移動する場合は、次のコマンドを...

Linux で TCP 接続の最大数をテストする方法

序文TCP サーバの最大同時接続数に関して、「ポート番号の上限が 65535 であるため、TCP サ...

別の種類の「キャンセル」ボタン

「キャンセル」ボタンは必要な操作プロセスの一部ではなく、デザイン上の主要な要素として表示されません...

MySQLでテーブルを接続するいくつかの方法

MySQL テーブルでの接続方法は実は非常に簡単なので、ここではその特徴を簡単にリストします。テーブ...

JavaScript の toLocaleString() での時間フォーマットに関する新しいアイデア

目次1. 時刻表示に関する従来の考え方2. 時刻の書式設定 toLocaleString() Obj...

LINUX ポートが占有されているかどうかを確認します

ポートが占有されているかどうかは、これまで一度もわかりませんでした。多くの人に尋ねて、ようやくわかり...

el-select のスタイルを変更する方法の詳細な説明: popper-append-to-body と popper-class

elementUI が提供する el-select コンポーネントのスタイルを変更する方法この問題...

不規則な投影を実現するためのボックスシャドウとドロップシャドウのサンプルコード

border-radius で生成できる四角形やその他の図形に影を追加する場合 (「Adaptive...

Ubuntu 16.04.4LTS に mininet をインストールする際に発生する問題と解決策

ミニネットMininet は軽量のソフトウェア定義ネットワークおよびテスト プラットフォームです。軽...

Vueが学生管理機能を実装

この記事では、学生管理を実装するためのVueの具体的なコードを例として紹介します。具体的な内容は次の...

JavaScript関数導入の詳しい説明

目次機能紹介関数関数の作成コンストラクタは関数を作成する関数宣言は関数を作成する関数式関数を作成する...

UIエンジニアのキャリアについての私たちの考え

私は長い間落ち込んでいます、なぜでしょうか?以前、お客様から、提供されたソフトウェアが正常に動作しな...

VueとFlask間の通信の実装

axiosをインストールして通信を実装するここでは、axios を使用して Vue フロントエンドと...

星のフラッシュ効果を実現するjs

この記事の例では、スターフラッシュ効果を実現するためのjsの具体的なコードを参考までに共有しています...