Maison > interface Web > Voir.js > le corps du texte

Pourquoi Reflect doit-il être utilisé pour Proxy dans vue3 ?

PHPz
Libérer: 2023-06-01 18:55:06
avant
1416 Les gens l'ont consulté

Ceux qui ont utilisé Vue savent que l'implémentation de la réponse de Vue utilise Proxy et qu'elle est utilisée avec Reflect. La chose la plus frappante lorsque l'on regarde les documents Proxy et Reflect est que la méthode statique de l'objet Reflect porte le même nom que le proxy Proxy. La méthode Reflect peut être utilisée pour manipuler des objets. , le proxy peut proxy des objets, mais je n'ai pas trouvé pourquoi vous devez parfois utiliser Reflect dans la méthode proxy Proxy

Opérations de base

Les méthodes statiques de l'objet Reflect ont les mêmes noms. comme les méthodes de proxy proxy, et il existe 13 types de get et set sont les suivants

const tempObj = { a: 1 };
Reflect.get(tempObj, 'a'); // 返回 1
Reflect.set(tempObj, 'a', 2); // 返回true 表示设置成功, a的值变2

const tempObj1 = { a: 1 };
const handler = {
  get: function (obj, prop, receiver) {
    return prop === 'a' ? 1000 : obj[prop];
  },
  set: function (obj, prop, value, receiver) {
    console.log(prop);
    obj[prop] = prop === 'a' ? 6 : value;
    return true;
  },
};
const proxyObj = new Proxy(tempObj1, handler);
proxyObj.a; // proxyObj => {a: 1000}
proxyObj.a = 2; // proxyObj => {a: 6}
Copier après la connexion

Question

Si le proxy n'effectue pas d'autres opérations et renvoie directement

const tempObj1 = { a: 1 };
const handler = {
  get: function (obj, prop, receiver) {
    return obj[prop];
  },
  set: function (obj, prop, value, receiver) {
    obj[prop] = value
    return true;
  },
};
const proxyObj = new Proxy(tempObj1, handler);
proxyObj.a; // proxyObj => {a: 1}
proxyObj.a = 2; // proxyObj => {a: 2}
Copier après la connexion

Dans la situation ci-dessus, le proxy peut gérer l'interception sans en utilisant Reflect, ce qui est beaucoup plus simple que d'utiliser Reflect

Différents objets, objets avec get

const tempObj1 = {
  a: 1,
  get value() {
    console.log(this === proxyObj); // false
    return this.a;
  },
};
const handler = {
  get: function (obj, prop, receiver) {
    return obj[prop];
  },
  set: function (obj, prop, value, receiver) {
    obj[prop] = value;
    return true;
  },
};
const proxyObj = new Proxy(tempObj1, handler);
proxyObj.value; // 1
Copier après la connexion

La valeur imprimée dans la valeur ci-dessus est fausse et le résultat attendu doit être vrai, mais l'objet d'origine utilisé dans le proxy doit être la valeur, donc cela pointe vers l'objet d'origine, donc la valeur est fausse

Bien que cela pointe vers le mauvais, mais la valeur est toujours correcte Ce n'est pas une certaine raison

const parent = {
  a: 1,
  get value() {
    console.log(this === child); // false
    return this.a;
  },
};
const handler = {
  get: function (obj, prop, receiver) {
    return obj[prop];
  },
  set: function (obj, prop, value, receiver) {
    obj[prop] = value;
    return true;
  },
};

const proxyObj = new Proxy(parent, handler);
const child = Object.setPrototypeOf({ a: 2 }, proxyObj);
child.value; // 1
Copier après la connexion

Il y a un problème. Les résultats de sortie sont différents de ceux attendus. Cela devrait pointer vers l'enfant, mais cela pointe vers le parent

Reflect s'allume

Si Reflect.get(obj, prop) est remplacé par obj[prop]. Cela équivaut à aucun changement. La signification et le résultat sont les mêmes. N'y a-t-il pas un autre paramètre du récepteur qui est inutile ? correctement, et le résultat est bien sûr conforme aux attentes. receiver ne fait pas référence à l'objet proxy, ni à l'objet d'origine, mais au contexte d'exécution (avec La phrase est comme ça, sans changer cela dans d'une manière spécifique, celui qui appelle pointe vers qui, c'est ce qui est attendu), ici enfant appelle valeur, donc le point attendu devrait être enfant</code >. Ici, vous pouvez penser à utiliser directement <code>receiver[prop], mais cela ne fonctionnera pas. Cela entraînera un débordement d'exécution. receiver[prop] est équivalent à . child.value, child.value n'a pas encore été exécuté, et receiver[prop] est à nouveau exécuté, et il continuera à s'exécuter indéfinimentReflect.get(obj, prop)换成obj[prop],这等于没换,意义和结果是一样的,这不是还有一个receiver参数没有用嘛

const parent = {
  a: 1,
  get value() {
    console.log(this === child); // true
    return this.a;
  },
};
const handler = {
  get: function (obj, prop, receiver) {
    Reflect.get(obj, prop)
   - return obj[prop];
   + retrun Reflect.get(obj, prop, receiver)
  },
  set: function (obj, prop, value, receiver) {
   - obj[prop] = value;
   + Reflect.get(obj, prop, value, receiver)
    return true;
  },
};

const proxyObj = new Proxy(parent, handler);
const child = Object.setPrototypeOf({ a: 2 }, proxyObj);
child.value; // 2
Copier après la connexion

this指向正确,结果也当然和期望一致,receiver的不是指代理对象,也不是指原对象,而是执行上下文(有句话是这么说的,不用特定方式改变this的情况下,谁调用指向谁,这就是期望的),这里child调用的value所以期望的指向应该是child, 这里你可能想到直接用receiver[prop]不行了,这样会出现执行溢出,receiver[prop]相当于child.valuechild.value还没执行完,receiver[prop]又执行了,就会无限在执行

Reflect.get(target, key, receiver)中的receiver参数修改了this指向,不加this指向target, 加了后指向receiver

代理对象中有用到this时一定要用到Reflect,这样才能得到一直符合期望的值

总结

vue3中的代理对象到得的都是符合期望的值,在拦截中做了收集和更新,所以一定要在Proxy的拦截函数中使用Reflect

Le paramètre receiver dans Reflect.get(target, key, Receiver) modifie le pointeur this sans ajouter this Pointez sur target, puis sur receiver🎜🎜🎜🎜Lorsque this est utilisé dans l'objet proxy, assurez-vous d'utiliser Réfléchissez</ code>, de cette façon, nous pouvons obtenir les valeurs attendues à tout moment🎜🎜🎜Résumé🎜🎜Les objets proxy dans vue3 obtiennent les valeurs attendues. Ils sont collectés et mis à jour lors de l'interception, ils doivent donc l'être. dans <code>Proxy< Utilisez <code>Reflect dans la fonction d'interception de /code> pour traiter🎜🎜Comment toujours obtenir la valeur attendue, le proxy est comme s'il n'y avait pas de proxy🎜
  get: function (...arg) {
    return Reflect.get(...arg);
  },
Copier après la connexion

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:yisu.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal