Vue3 がデータ監視を実装するためにプロキシを使用する理由の分析

Vue3 がデータ監視を実装するためにプロキシを使用する理由の分析

Vue データの双方向バインディング原則ですが、この方法には欠点があり、配列とオブジェクトの部分的な監視を実装できません。詳細については、以前に書いたブログ「Vue が配列とオブジェクトの変更を監視できない問題の解決方法」も参照してください。最新の Proxy は、Vue2 の Object.defineProperty と比較して、速度が 2 倍になり、メモリが半分になる効果を実現できます。どのように実装されているか、また、なぜ従来の実装方法に比べて速度が 2 倍になり、メモリが半分になるのかについて説明します。

Vue 初期化プロセス

Vue の初期化プロセスには、Observer、Compiler、Watcher が含まれます。新しい Vue を作成すると、Observer が呼び出され、Object.defineProperty を通じて Vue オブジェクトのデータ、計算値、または props (コンポーネントの場合) のすべてのプロパティを監視します。同時に、テンプレート命令はコンパイラによって解析されます。属性が解析された後、新しいウォッチャーが作成され、更新関数がウォッチャーにバインドされます。オブザーバーとコンパイラーは属性を通じて関連付けられます。

オブジェクト.defineProperty

簡単なObject.definePropertyの例を見てみましょう

クラスオブザーバー{
    コンストラクタ(データ) {
      // パラメータデータのプロパティを走査し、これをこれに追加します for (let key of Object.keys(data)) {
        if (typeof data[key] === "object") {
          データ[キー] = 新しいオブザーバー(データ[キー]);
        }
        Object.defineProperty(this, キー, {
          列挙可能: true、
          設定可能: true、
          得る() {
            console.log("訪問した" + キー); //訪問した年齢
            データ[キー]を返す;//20
          },
          set(newVal) {
            console.log("You set" + key); //年齢を設定しました
            console.log("new" + key + "=" + newVal); //新しい年齢=20
            if (newVal === data[key]) {
              戻る;
            }
            データ[キー] = newVal;
          }
        });
      }
    }
  }定数オブジェクト = {
    名前:「アプリ」、
    年齢: "18",
    a: {
      b: 1、
      c: 2,
    }
  };const app = new Observer(obj);app.age = 20;console.log(app.age);app.newPropKey = "新しいプロパティ";console.log(app.newPropKey); //新しいプロパティ

上記から、Object.defineProperty はすべてのプロパティをトラバースする必要があることがわかります。つまり、vue オブジェクトの data/computed/props のデータ サイズが大きい場合、トラバースは大幅に遅くなります。同様に、vue オブジェクトの data/computed/props のデータ サイズが大きい場合、Object.defineProperty はすべてのプロパティの変更を監視する必要があり、大量のメモリを占有します。

プロキシ

プロキシを見てみましょう

プロキシ オブジェクトは、基本的な操作 (プロパティの検索、割り当て、列挙、関数呼び出しなど) のカスタム動作を定義するために使用されます。

これは、オブジェクトの前に「インターセプション」を設定することと理解できます。監視対象オブジェクトにアクセスする場合、このインターセプション層を通過する必要があります。このインターセプションでは、元のオブジェクトを処理し、必要なデータ形式を返すことができます。つまり、オブジェクトのどの属性にアクセスしても、それが以前に定義された属性であっても、新しく追加された属性であっても、インターセプションで処理されます。これにより、以前は監視できなかった問題が解決されます。

定数オブジェクト = {
  名前: "krry",
  年齢: 24歳
  その他:
    モバイル: "mi10",
    ウォッチ: "mi4",
  },};const p = new Proxy(obj, {
  get(ターゲット、キー、受信者) {
    console.log("表示するプロパティは次のとおりです: " + キー);  
    Reflect.get(ターゲット、キー、レシーバー) を返します。
  },
  set(ターゲット、キー、値、レシーバー) {
    console.log("設定されたプロパティは: " + キーです); 
    console.log("新しいプロパティ: " + キー、"値: " + 値); 
    Reflect.set(ターゲット、キー、値、レシーバー);
  },});p.age = 22;console.log(p.age); p.single = "NO";console.log(p.single);p.others.shoe = "boost";console.log(p.others.shoe);出力結果は次のとおりです:設定されたプロパティは次のとおりです: age
新しい属性: age 値: 22 表示する属性: age22

設定するプロパティは、singleです。
新しい属性: single 値: NO 表示する属性: singleNO 表示する属性: other
表示するプロパティは次のとおりです: その他
ブースト

上で見たように、Proxy はオブジェクトに対する操作なので、プロパティの追加や編集にはレスポンシブな処理を再度追加する必要がなく、すべてを監視できます。オブジェクトにアクセスする限り、Proxy のロジックに入ります。 Reflect は、JavaScript 操作をインターセプトするためのメソッドを提供する組み込みオブジェクトです。これらのメソッドは、プロキシ ハンドラーのメソッドと同じです。 Reflect は関数オブジェクトではないため、構築できません。Proxy と Object.defineProperty の違いは使用方法が非常に似ているように見えますが、Proxy は実際にはより高い次元でプロパティをインターセプトします。

Object.definePropertyVue2 では、{ count: 1 } などの特定のデータに対して、特定のキー、つまり count に基づいて get と set をインターセプトする必要があります。

Object.defineProperty(データ、'count'、{
  得る() {}、
  セット() {}、})

インターセプトするキーが何であるかを事前に知っておく必要があります。これが、Vue2 がオブジェクトの新しい属性に対して無力である理由です。したがって、Vue の初期化中に、データの変更を保持するためにデータをトラバースする必要があり、速度が低下し、メモリ使用量が増加します。

プロキシ Vue3 で使用されるプロキシは次のようにインターセプトします。

新しいプロキシ(データ、{
  get(キー) { },
  set(キー、値) { },})

ご覧のとおり、プロキシは特定のキーを気にする必要はありません。プロキシは、データ上の任意のキーの変更と、データ上の任意のキーの読み取りを傍受します。

したがって、既存のキーと新しく追加されたキーの両方が監視されます。

これで、Vue3 が Proxy を使用してデータ監視を実装する理由の分析に関するこの記事は終了です。Vue3 が Proxy を使用してデータ監視を実装する理由の詳細については、123WORDPRESS.COM の以前の記事を検索するか、次の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM を応援してください。

以下もご興味があるかもしれません:
  • Vue3はクロスドメイン問題を解決するためにプロキシを設定します
  • Vue3でプロキシパッケージデータを取得する方法
  • Vue3 のプロキシの簡単な実装の詳細説明 プロキシの例
  • プロキシはVue3データの双方向バインディングの原理を実現します
  • Vue3 のプロキシの基本的な使用方法

<<:  リアルタイムコンピューティングフレームワークFlinkクラスタの構築と動作メカニズムについての簡単な説明

>>:  HTML で Flash を読み込む方法 (2 つの実装方法)

推薦する

VueでEchartsチャートの幅と高さの適応を実現する実践

目次1. インストールとインポート2. 手ぶれ補正機能を定義する3. チャートコードを描くinit ...

フロントエンド開発に必須:推奨されるブラウザ互換性テストツール 12 選

フロントエンド開発者にとって、さまざまな主要ブラウザのさまざまなバージョンでコードが適切に動作するこ...

Maven+Tomcat 基本イメージを構築する Docker の実装

序文Javaプログラミングでは、ほとんどのアプリケーションはMavenに基づいて構築されており、配信...

CSS flex 複数列レイアウト

基本的な3列レイアウト 。容器{ ディスプレイ: フレックス; 幅: 500ピクセル; 高さ: 20...

CentOS 8/RHEL 8 に Cockpit をインストールして使用する方法

Cockpit は、CentOS および RHEL システムで使用できる Web ベースのサーバー管...

Linux での GDB 入門チュートリアル

序文gdb は Linux で非常に便利なデバッグ ツールです。コマンドライン モードのデバッグ ツ...

Linuxテキスト処理ツールの詳細な説明

1. /etc/passwdファイル内のデフォルトシェルが/sbin/nologinではないユーザー...

CSS マージンの折りたたみの詳細な説明

前のこれは古くからある古典的な質問です。以前読者から質問があったので、ここでお答えします。簡単な例か...

より人気がありクリエイティブなダーク背景のウェブデザインの例

暗い背景スタイルのページ デザインは非常に人気があり、シックでエレガント、そして非常にクリエイティブ...

JavaScript で H5 ゴールド コイン関数を実装する (サンプル コード)

今日は春節の金貨の赤い封筒のアクティビティを作りました。なかなか良い出来だと思います。皆さんと共有し...

MySQLに必要な共通知識のまとめ

目次主キー制約一意の主キー非 Null 制約デフォルトの制約外部キー制約1NF 2NF 3NFデータ...

Mysql general_log をクリーンアップする方法の概要

方法1: グローバル general_log を 'OFF' に設定します。 テーブ...

MySQL マスタースレーブ構築(複数のマスターと 1 つのスレーブ)の実装アイデアと手順

背景:最近、同社のプロジェクトは同時実行のプレッシャーに耐えられないようなので、最適化が差し迫ってい...

Web デザインにおける Less と More について語る (写真)

Less is More は多くのデザイナーのキャッチフレーズです。これは建築界の巨匠ルートヴィヒ...

Linux での fuser コマンドの使用法の詳細な説明

説明する: fuser は、現在ディスク上のファイル、マウント ポイント、さらにはネットワーク ポー...