vue3中的Proxy一定要用Reflect的原因解析

 更新时间:2023年04月23日 10:31:27   作者:L_J_K  
Reflect可以操作对象使用, proxy可以代理对象,但没有找到为啥有时一定要在Proxy代理方法中使用Reflect,这篇文章主要介绍了vue3中的Proxy一定要用Reflect的原因解析,需要的朋友可以参考下

用过vue的知道,vue的响应实现用的Proxy,且里面是配合Reflect用的,查看Proxy和Reflect文档最显眼的是Reflect对象的静态方法和Proxy代理方法的命名相同,Reflect可以操作对象使用, proxy可以代理对象,但没有找到为啥有时一定要在Proxy代理方法中使用Reflect

基本操作

Reflect对象的静态方法和Proxy代理方法的命名相同,都有13种,示例get,set如下

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}

疑问

如果Proxy不做其它操作直接正常返回

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}

以上面情况完Proxy可以不使用Reflect处理拦截,比使用Reflect简单多了

不一样的对象, 带有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

上面value中的打印的值为false,期望的结果应该true, 但应该代理中用的原对象取值所以this指向了原对象,所以值为false

虽然this指错了,但得到值还是正确定,这不是一定的理由

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

这就有问题了,输出的结果都和期望的不一样了,this应该指向child,但指向了parent

Reflect上场

要是Reflect.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

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处理

怎么一直拿到符合期望的值,代理了像没有代理一样

  get: function (...arg) {
    return Reflect.get(...arg);
  },

到此这篇关于为啥vue3中的Proxy一定要用Reflect的文章就介绍到这了,更多相关vue3中Proxy使用Reflect内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • vue项目打包清除console.log的四种方法总结

    vue项目打包清除console.log的四种方法总结

    大家在项目开发的时候,需要看看一些后端接口返回的结果,会多次使用console.log项目开发完成打包的时候,发现控制台一堆的console.log,非常头疼,下面这篇文章主要给大家介绍了关于vue项目打包清除console.log的四种方法,需要的朋友可以参考下
    2023-04-04
  • vue路由相对路径跳转方式

    vue路由相对路径跳转方式

    这篇文章主要介绍了vue路由相对路径跳转方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • vue如何修改浏览器的标题title

    vue如何修改浏览器的标题title

    这篇文章主要介绍了vue如何修改浏览器的标题title问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-10-10
  • vue3成功创建项目后 run serve启动项目报错的解决

    vue3成功创建项目后 run serve启动项目报错的解决

    这篇文章主要介绍了vue3成功创建项目后 run serve启动项目报错的解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-03-03
  • vue限制输入框只能输入8位整数和2位小数的代码

    vue限制输入框只能输入8位整数和2位小数的代码

    这篇文章主要介绍了vue限制输入框只能输入8位整数和2位小数,文中我们使用v-model加watch 实现这一个功能,代码简单易懂,需要的朋友可以参考下
    2019-11-11
  • vue实现购物车的监听

    vue实现购物车的监听

    这篇文章主要为大家详细介绍了利用vue的监听事件实现一个简单购物车,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-04-04
  • vue3在构建时使用魔法糖语法时defineProps和defineEmits的注意事项小结

    vue3在构建时使用魔法糖语法时defineProps和defineEmits的注意事项小结

    在 Vue 3.2+ 版本中,可以使用 <script setup> 替代传统的 script标签来编写组件,它提供了更简洁的语法来编写 Composition API 代码,这篇文章主要介绍了vue3在构建时使用魔法糖语法时defineProps和defineEmits的注意事项小结,需要的朋友可以参考下
    2024-04-04
  • Vue中自定义全局组件的实现方法

    Vue中自定义全局组件的实现方法

    这两天学习了Vue.js 感觉组件这个地方知识点挺多的,而且很重要,所以这篇文章主要给大家介绍了关于Vue中自定义全局组件的实现方法,文中通过示例代码介绍的非常详细,对大家学习或者使用vue具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
    2017-12-12
  • vue2路由方式--嵌套路由实现方法分析

    vue2路由方式--嵌套路由实现方法分析

    这篇文章主要介绍了vue2嵌套路由实现方法,结合实例形式分析了vue2嵌套路由基本实现方法与操作注意事项,需要的朋友可以参考下
    2020-03-03
  • vue教程之toast弹框全局调用示例详解

    vue教程之toast弹框全局调用示例详解

    这篇文章主要为大家详细介绍了vue教程之toast弹框全局调用示例,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-08-08

最新评论