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

推薦する

携帯電話番号の真ん中の4桁を隠すMySQL SQL文の方法

最初のクエリ テーブル構造 (sys_users): sys_users から * を選択します。最...

Vueはページに透かし効果を追加する機能を実装します

最近、あるプロジェクトに取り組んでいたとき、ページに透かし効果を追加するように依頼されました。さっそ...

Windows 10 で MySQL 8.0.12 の解凍バージョンをインストールして構成する方法 (グラフィック チュートリアル付き)

この記事では、MySQL 8.0.12 の解凍版のインストールと設定方法を記録し、皆様と共有します。...

Vue ベースの Excel 解析とエクスポートの詳細な説明

目次序文基本的な紹介コードの実装基本構造アップロード分析Excel にエクスポート基本構造Excel...

mysql mycat ミドルウェアのインストールと使用

1. mycatとはエンタープライズアプリケーション開発のための完全にオープンソースの大規模データベ...

Node.jsミドルウェアの仕組みの詳細な説明

目次Express ミドルウェアとは何ですか? Expressミドルウェアを作成するための要件Exp...

Win10 での MySQL 8.0.20 のインストールと設定のチュートリアル

Win10 システムでの MySQL 8.0.20 のインストールと設定の超詳細なチュートリアルMy...

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

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

Mysql でよく使用される時間、日付、変換関数の概要

この記事では、主に実際のアプリケーションでよく使用されるMySQLの時刻と日付、および変換関数につい...

ビジネス HTML メール作成に関する提案

許可ベースの電子メール マーケティングにより、マーケティングとプロモーションのコストを大幅に削減でき...

Dockerリポジトリの一般的なコマンドの詳細な説明

ログイン dockerログインdocker login コマンドを実行し、ユーザー名、パスワード、メ...

MySQLでNULL値を判定する際の落とし穴事例

目次序文Mysql の case when 構文:事例実践:要約:序文今日、プログラムを開発している...

グローバルトーストコンポーネントをカプセル化するVueの完全な例

目次序文1. vue-cliを使う1. Toastコンポーネントを定義する2. main.jsで設定...

Springboot+Vue-Cropperでアバターの切り取りとアップロードの効果を実現

アバターをアップロードするにはVue-Cropperコンポーネントを使用します。参考までに具体的な内...