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

推薦する

5分でDockerを使ってRedisのクラスターモードとセンチネルモードを構築する方法を教えます

目次1. 準備Redisイメージを取得する2. Redis Sentinel マスタースレーブモード...

CSS を使用して複数の方法で下揃えを実装するサンプル コード

会社のビジネス要件により、次の図の赤い領域の効果を達成する必要があります。 効果の説明: 1. 赤い...

MySQLからOracleへのリアルタイム同期ソリューションの詳細な説明

1 要件の概要MySQL5.6本番データベースの複数のテーブルのデータは、Oracle11gデータウ...

MySQL関数の包括的な概要

目次1. MySQLでよく使われる文字列関数2. 数値関数3. 日付と時刻の機能4. プロセス機能5...

Vue要素と多言語切り替えの詳細な説明

目次序文複数の言語を切り替えるにはどうすればいいですか? 1. vue-i18nパッケージをインスト...

MySQL の count()、group by、order by の詳細な説明

最近、IM を実行するときに、これらの 3 つのキーワードを同時に使用したときに問題が発生しました。...

Tomcat Nativeを使用してTomcat IO効率を向上させる方法の詳細な説明

目次導入Tomcatへの接続方法APR と Tomcat ネイティブtomcat で APR を使用...

SQLの最適化では間違いがよく起こります。それはMySQLのExplain Planの使い方を理解していないからです。

目次1. 準備2. 説明計画の概要3. フィールドの詳細な説明4. パーティションクエリにはパーティ...

Linux システムでキャッシュをクリアする方法の概要

1) キャッシュメカニズムの紹介Linux システムでは、ファイルシステムのパフォーマンスを向上させ...

Centos7.x での Nginx のインストール、SSL 設定、一般的なコマンドの詳細な説明

1. インストールyumを使用してインストールする ##yum nginx を自動的にインストールす...

ドロップダウンメニューを実装するためのネイティブ js

ドロップダウン メニューも実生活では非常に一般的です。実装に使用される js コードは、タブ選択やア...

商品クエリ機能を実現するJavaScript

この記事の例では、商品検索機能を実現するためのJavaScriptの具体的なコードを参考までに共有し...

WeChatアプレットはふるいを振る効果を実現

この記事では、WeChatアプレットの具体的なコードを参考までに共有します。具体的な内容は次のとおり...

Vue で計算プロパティを使用する際の知識ポイントのまとめ

計算されたプロパティ場合によっては、テンプレートにロジックを詰め込みすぎると、テンプレートが重くなり...

Vueナンバープレート入力コンポーネントの使い方の詳しい説明

参考までに、シンプルなナンバープレート入力コンポーネント(vue)です。具体的な内容は次のとおりです...