Vue2 と vue3 の双方向データ バインディングの原理、ES6 の Proxy オブジェクト proxy と JavaScript の Object.defineProperty、詳細な使用法

はじめに: Object.defineProperty が vue2 の双方向データ バインディングの原理であることは誰もが知っています。これは、オブジェクト プロパティを定義するために JavaScript で一般的に使用される強力なメソッドであり、読み取り、書き込み操作を含むプロパティの動作を正確に制御できるようになります。入力や削除など。

プロキシは、vue3 の双方向データ バインディングの原理です。これは、ES6 でプロキシ オブジェクトを作成するために使用される特別なオブジェクトです。これにより、属性アクセス、割り当て、関数呼び出し、ターゲット オブジェクトの操作をインターセプトしてカスタマイズできます。等 プロキシは、ターゲット オブジェクト上の操作をインターセプトするためにターゲット オブジェクトにインターセプターを設定するメカニズムを提供します。

一、Object.defineProperty

1. Object.defineProperty は、オブジェクト プロパティを定義または変更するためのメソッドであり、書き込み可能性、列挙可能性、構成可能性などのプロパティの動作を正確に制御できます。Object.defineProperty メソッドには、3 つの必須パラメータとオプションの 4 つ目のパラメータがあります

  1. obj (必須): プロパティを定義するオブジェクト。任意の JavaScript オブジェクトを使用できます。
  2. prop (必須): 定義または変更するプロパティの名前。プロパティの名前を表す文字列を指定できます。
  3. 記述子 (必須): プロパティのプロパティを定義または変更するオブジェクト。

次のオプションの属性も含めることができます

- 構成可能 (オプション): 属性を削除または変更できるかどうかを示すブール値。デフォルトは false です。

- enumerable (オプション): プロパティを for...in ループで列挙できるかどうかを示すブール値。デフォルトは false です。

- value (オプション): 属性の初期値を表す任意のタイプの値。デフォルトは未定義です。

- writable (オプション): プロパティの値を変更できるかどうかを示すブール値。デフォルトは false です。

- get (オプション): プロパティ値を取得するときに呼び出される関数を表す関数。

- set (オプション): function。プロパティ値を設定するときに呼び出される関数を表します。

2.基本的な文法 (詳細についてはコメントを参照してください)

  const obj = {    name: "小明", age: 18    }
  //或者
  const obj = {    }

  //这里不能使用const,const定义的是常量,无法修改;
  let demoBute= obj.name;
  
  //使用 Object.defineProperty 定义属性名为 name 的属性
  Object.defineProperty(obj, "name", {

    //可枚举属性,可以在 for...in 循环中被枚举
    enumerable: true,
    //可配置属性,可以使用 delete 运算符删除属性
    configurable: true,

    //获取属性值的函数
    get: function () {
      console.log("获取,收集依赖");
      return demoBute
    },

    //设置属性值的函数
    set: function (value) {
      console.log("更新,通知用户");
      demoBute = value;
    }

  })
    
  //修改,触发set函数
  obj.name = "小红"
  //控制台输出:更新,通知用户
  
  //调用,出发get函数
  console.log(obj.name);
  //控制台输出:获取,收集依赖
              //小明
  
  //多次调用,看下运行顺序,按照调用顺序依次执行(set > get > log)
  //只要调用obj都会触发依赖函数
  obj.name = "小红";             //set >
  console.log(obj.name);         //get > log
  //控制台输出: 
  //更新,通知用户
  //获取,收集依赖
  //小红

3.取得と設定

  •  get 関数の役割は、プロパティ値にアクセスするときに呼び出されることであり、パラメータは受け入れませんが、プロパティの値を返す必要があります。この例では、return demoBute を通じて name の属性値を返します。
  • set 関数の役割は属性値を設定するときに呼び出され、設定する属性値を示すパラメーター値を受け取ります。この例では、変更された値 value を demoBute に直接割り当てて、更新を実装します。

4.注意すべき事項

  1. get 関数と set 関数は同時にトリガーされず、プロパティの読み取りまたは設定操作に従ってどの関数を呼び出すか決定します。
  2. このメソッドは呼び出し順序に従って上から下へ順番に実行されます。つまり、更新がある場合は set 関数のみが実行され、更新がない場合は get 関数のみが実行されます。

二、Proxy

1. Proxy メソッドは、オブジェクトをインターセプトしてカスタマイズできるようにする基礎となる操作です。プロキシを使用すると、属性アクセス、属性の割り当て、関数呼び出しなどのオブジェクトのさまざまな操作をインターセプトし、これらの操作が発生したときにカスタム動作を実行できます。プロキシのターゲットは、プロキシするターゲット オブジェクトです。 handler は、さまざまなインターセプト操作を含むオブジェクトです。ハンドラー オブジェクトの各プロパティは、さまざまな操作をインターセプトするために使用される特別なインターセプターです

2.基本的な文法

const target = {...... }

const handler = {
    get(target, property, receiver){
    //拦截属性的读取操作
    },
    set(target, property, value, receiver){
    //拦截属性
    }
}

​​​​​​​const proxy = new Proxy(target, handler);

3. ES6 のプロキシでは、get と set が一般的に使用される 2 つのインターセプター関数であり、オブジェクト プロパティの読み取りと割り当てをインターセプトするために使用されます。以下に、これら 2 つの関数の使用法と機能について詳しく説明します。

(1)、get (ターゲット、プロパティ、レシーバー)

- target: ターゲット オブジェクト、つまりプロキシされるオブジェクト。

- property : アクセスするプロパティ名。

- レシーバー: 最初に呼び出されたオブジェクト。通常はプロキシ オブジェクトまたはプロキシ オブジェクトを継承するオブジェクトです。- 戻り値: プロパティの値を返します。

get 関数は、ターゲット オブジェクトのプロパティにアクセスするとトリガーされ、プロパティの読み取り操作をインターセプトするために使用できます。get 関数内に、ログ記録やアクセス権の検証などのカスタム ロジックを追加できます。以下に例を示します。

const target = {
  name: "Bob",
  age: 18
};
const handler = {
  get(target, property, receiver) {
    console.log(`正在读取属性:${property}`);
    return target[property];
  }
};
const proxy = new Proxy(target, handler);
console.log(proxy.name); // 输出:正在读取属性:name,Bob
console.log(proxy.age); // 输出:正在读取属性:age,18

ここでは、プロキシ オブジェクト proxy を作成します。プロキシのプロパティにアクセスすると、get 関数がトリガーされ、対応するログ情報が出力されます。

(2)、セット(ターゲット、プロパティ、値、受信者) 

- target : ターゲット オブジェクト、つまりプロキシされるオブジェクト。

- property : 設定するプロパティ名。

- value : 設定するプロパティ値。

-レシーバ: 最初に呼び出されたオブジェクト。通常はプロキシ オブジェクト、またはプロキシ オブジェクトから継承したオブジェクトです。- 戻り値: 属性が正常に設定されたかどうかを示すブール値を返します。​​​​​​​​

set 関数は、ターゲット オブジェクトの属性に値を割り当てるときにトリガーされ、属性の割り当て操作をインターセプトするために使用できます。割り当ての有効性の検証、ログの記録など、set 関数内にカスタム ロジックを追加できます。以下に例を示します。

const target = {
  name: "Carl",
  age: 20
};
const handler = {
  set(target, property, value, receiver) {
    console.log(`正在设置属性:${property},新值为:${value}`);
    target[property] = value;
    return true;
  }
};
const proxy = new Proxy(target, handler);
proxy.age = 30; // 输出:正在设置属性:age,新值为:30
console.log(proxy.age); // 输出:30

ここで、プロキシの age 属性に値を割り当てると、set 関数がトリガーされ、対応するログ情報が出力されます。get および set インターセプタ関数を通じて、属性の読み取りと割り当て時にカスタム動作を実行できます。より柔軟で制御可能なオブジェクト操作を実現します。

(3)、get と setの完全な例

const target = {
  name: "Alice",
  age: 25
};

const handler = {
  get(target, property, receiver) {
    console.log(`正在读取属性:${property}`);
    return target[property];
  },
  set(target, property, value, receiver) {
    console.log(`正在设置属性:${property},新值为:${value}`);
    target[property] = value;
    return true;
  }
};

const proxy = new Proxy(target, handler);

console.log(proxy.name);     // 输出:正在读取属性:name,Alice
proxy.age = 30;             // 输出:正在设置属性:age,新值为:30
console.log(proxy.age);     // 输出:正在读取属性:age,30

4.ハンドラーオブジェクトのその他のパラメーター

  •  get(ターゲット, プロパティ, レシーバー): プロパティの読み取り操作をインターセプトします。
  •  set(ターゲット, プロパティ, 値, レシーバー): プロパティの割り当てをインターセプトします。
  •  apply(target, thisArg, argumentList): 関数呼び出し操作をインターセプトします。
  •  has(target, property): in 演算子の操作をインターセプトします。
  •  deleteProperty(target, property): プロパティの削除をインターセプトします
  •  ……

おすすめ

転載: blog.csdn.net/weixin_65793170/article/details/131570332