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 プライベート クラウド ストレージ ネットワーク ディスクの構築に関する詳細なチュートリアル

推薦する

Vue プラグイン エラー: このページで Vue.js が検出されました。問題は解決しました

Vue プラグインがエラーを報告しました: このページで Vue.js が検出されましたVueプラグ...

Linux システムでデプロイメント プロジェクトを設定する方法

1. ファイアウォールの設定を変更し、対応するポートを開きますLinux システムのファイアウォール...

JavaScript 関数のパフォーマンスを測定するさまざまな方法の比較

目次概要パフォーマンス.nowコンソール.time時間精度を短縮注意事項分割して征服する入力値に注意...

Centos Docker ブリッジ モードでホスト Redis サービスにアクセスできないというトラブルシューティングの経験

背景:以前、コンテナ内のホストが提供する Redis サービスにアクセスする必要があるプロジェクトを...

遭遇したいくつかのブラウザ互換性の問題について簡単に説明します

背景ブラウザの互換性の問題を解決するのは非常に面倒なことです。高度な技術はそれほど必要ありませんが、...

浮遊要素によって引き起こされる問題と解決策の詳細な説明

1. 問題複数のフローティング要素は親要素の幅を拡張できず、親要素の高さが 0 になる可能性がありま...

Docker コンテナのネットワーク障害に対する 6 つの解決策

Docker コンテナのネットワーク障害に対する 6 つの解決策注: 以下の方法は、コンテナ内のパブ...

MySQL でコマンドを使用して階層検索を実現する方法の詳細な説明

序文この記事は主にMySQLコマンド階層検索ヘルプの使用に関する内容を紹介します。この記事のサンプル...

MySQL サービスに iptables ファイアウォール ポリシーを追加するためのソリューション

MySQL データベースが Centos7 システムにインストールされており、オペレーティング シス...

MySQL での数値のフォーマットの詳細な説明

最近、仕事の都合で、MySQL で数字をフォーマットする必要がありましたが、インターネット上にはほと...

Docker で Kong API Gateway をインストールして使用する詳細なチュートリアル

1 はじめにKong は単純な製品ではありません。この記事で言及されている Kong は主に Kon...

NginxとLuaによるグレースケールリリースの実装

memcachedをインストールする yum インストール -y memcached #memcac...

JavaScript ES6 モジュールの詳細な説明

目次0. モジュールとは何か1.モジュールの読み込み1.1 方法1 1.2 方法2 2. 輸出と輸入...

MySQL テーブルスペースのリカバリに対する正しいアプローチについての簡単な説明

目次予備的注釈問題の再現データ削除の原則データの再利用どの操作がデータホールの原因になりますか?表領...

Dockerでボリュームを管理する2つの方法

前回の記事では、Dockerの基礎知識であるローカルディレクトリのマウント方法を紹介しました。今日は...