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 つの実装方法)

推薦する

Redux Toolkit で Redux を簡素化する方法

目次Redux Toolkitが解決する問題何が含まれていますか? Redux Toolkit AP...

CSS3 で作成したホバーズーム効果

結果:実装コード: html <link href='https://fonts.go...

VMware インストール後に仮想ネットワーク カードが表示されない問題について

1 問題の説明: 1.1 Windows 10 に VMware を初めてインストールする場合、また...

CSSは、入力ボックスのフローティングテキスト効果を実現するために、placeholder-shown疑似クラスを使用します。

この記事では、:placeholder-shown 疑似クラスを使用して、純粋な CSS で浮動疑問...

geo モジュールを使用して Nginx でホワイトリストを設定する例

元の構成: http { ...... limit_conn_zone $binary_remote...

背景位置パーセンテージ原則の詳細な説明

今日、誰かがコードを調整するのを手伝っていたとき、次のようなスタイルを見つけました。 背景位置: 5...

nginx のスムーズな再起動を実装する方法

1. 背景サーバーの開発プロセスでは、新しいコードや構成をロードするためにサービスを再起動することが...

MySQL が「operate_time」エラーのデフォルト値が無効であると報告する問題を解決する

データベースでcreate tableステートメントを実行する テーブル `sys_acl` を作成...

MySQLのデッドロックチェック処理の通常の方法

通常、デッドロックが発生すると、重みが最も小さい接続が強制終了され、ロールバックされます。ただし、最...

Linux での scp および sftp コマンドの詳細な説明

目次序文1. SCPの使用法2. sftpを使用する3. scp と sftp の違いは何ですか?ど...

初心者向け入門チュートリアル: ドメイン名の解決とバインディング

では、ドメイン名を登録して仮想ホストを購入した後、IE でドメイン名を入力して Web サイトを開く...

CSSはリモコンのボタンを模倣する

注: このデモはミニプログラム環境でテストされており、他の h5 および pc Web ページにも適...

HTML文書の基本構造(Webページ作成の基礎知識)

HTMLの動作原理: 1. ローカル操作: ブラウザでhtmlファイルを開く2. リモートアクセス...

MySQLのストレージエンジンの詳細な説明

MySQL ストレージ エンジンの概要ストレージ エンジンとは何ですか? MySQL のデータは、さ...

Tomcat Nginx Redis セッション共有プロセス図

1. 準備ミドルウェア: Tomcat、Redis、Nginx Jar パッケージ: commons...