理解 Vue3 使用的 Proxy

Vue3放弃了Object.defineProperty,转而使用Proxy实现数据劫持,以解决深度遍历和新增属性监听的缺陷。Proxy提供了一种更高效的方式,只需劫持目标对象,就能拦截并控制对对象的访问。它能监听13种操作,并且支持取消操作。然而,使用Proxy后,对象的this会指向Proxy。这是一个关于Vue3数据响应式原理的探讨。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在 vue3 中放弃了 Object.defineProperty 来进行数据劫持,而改用了 Proxy 替代原本的方案。

Object.defineProperty 的缺陷在于需要深度遍历并对每一个属性进行劫持,而对于没有属性的数组而言,数组的索引也可以视为被劫持的属性,但是和对象相同,对于新增的元素而言,不会触发监听事件,vue 对此的解决方案是劫持数组原型链上的函数,即便如此也仍旧无法监听对数组长度的修改。

而使用 Proxy 进行劫持则弥补了这些缺陷,阮一峰的《ECMAScript6 入门》中对于 Proxy 是这样描述的:

Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。

相对于 Object.defineProperty 需要对每一个属性进行劫持,Proxy 则更加的便捷,只需要劫持需要监听的对象即可。

var obj = new Proxy({}, {
  get: function (target, propKey, receiver) {
    console.log(`getting ${propKey}!`);
    return Reflect.get(target, propKey, receiver);
  },
  set: function (target, propKey, value, receiver) {
    console.log(`setting ${propKey}!`);
    return Reflect.set(target, propKey, value, receiver);
  }
});
obj.count = 1
//  setting count!
++obj.count
//  getting count!
//  setting count!
//  2

// target 是需要被劫持的对象,handler 是劫持后定义的行为
var proxy = new Proxy(target, handler);
// 不过如果想要使得劫持起作用,必须要操作劫持后的对象(proxy)而不是原对象(target)

除了常用的 get/set 外,Proxy 可以定义13种拦截操作。并且 Proxy 还可以进行取消操作,可以通过 Proxy.revocable() 返回一个可取消的实例。

Proxy.revocable()的一个使用场景是,目标对象不允许直接访问,必须通过代理访问,一旦访问结束,就收回代理权,不允许再次访问。

而针对如此万能的 Proxy 需要注意的问题是当一个对象被劫持后该对象的 this 指向将变为 Proxy 。

点此访问我的个人博客

<think>好的,我现在要解决用户在Vue3使用proxy配置代理和引入模块的问题。首先,用户提到了两个主要需求:配置代理和引入模块。我需要结合用户提供的四个引用内容,整理出正确的步骤和方法。 首先看配置代理的部分。根据引用[1]和[2],Vue项目中通常使用proxyTable或proxy配置来解决跨域问题,特别是在开发环境下。不过Vue3可能使用的是Vite,而Vite的代理配置可能与Vue2的有所不同。引用[4]提到在Vue3.0+Vite+TS项目中配置proxy代理,需要使用vite.config.ts文件中的server.proxy选项。因此,我需要指导用户如何在这个文件中进行配置,包括设置目标(target)、路径重写(rewrite)以及是否需要改变origin。同时,用户可能需要处理多个不同端口或IP的接口,这可以通过配置不同的代理路径来实现,比如/api和/other。 然后是引入模块的问题。用户提到在引用模块时出现红色波浪线,但能正常运行。根据引用[3],这可能是TypeScript类型声明的问题。解决方法是在vite-env.d.ts文件中添加模块声明,特别是针对.vue文件的声明,这样TS就能正确识别这些模块了。此外,引用[4]还提到使用@路径别名,需要在vite.config.ts中配置resolve.alias,同时安装相关的类型声明文件,比如@types/node,以确保TypeScript能正确解析路径。 接下来要检查是否有遗漏或错误的地方。比如,代理配置是否正确,路径别名的配置是否需要额外的依赖。用户可能需要安装ts-node、tslib、@types/node等,如引用[4]所述。另外,确保用户理解环境配置和类型声明的重要性,避免运行时错误和IDE的警告。 最后,生成相关问题,帮助用户深入理解相关配置,比如不同场景下的代理配置、路径别名的其他应用、TS类型声明的作用,以及生产环境和开发环境配置的区别。这些扩展问题能帮助用户更好地应用所学知识。</think>在Vue3中配置代理和模块引入主要涉及以下两个场景: ### 一、配置代理(解决跨域) 1. **创建/修改vite.config.ts** ```typescript import { defineConfig } from &#39;vite&#39; import vue from &#39;@vitejs/plugin-vue&#39; import path from &#39;path&#39; export default defineConfig({ plugins: [vue()], server: { proxy: { // 基础代理配置 &#39;/api&#39;: { target: &#39;http://your-backend-server.com&#39;, changeOrigin: true, rewrite: (path) => path.replace(/^\/api/, &#39;&#39;) }, // 多接口配置示例 &#39;/other&#39;: { target: &#39;http://different-ip:3000&#39;, changeOrigin: true } } } }) ``` 2. **安装必要依赖(已配置TS时)** ```bash npm install -D @types/node ts-node tslib ``` 此配置可实现不同接口地址的代理转发[^1][^2][^4] ### 二、模块引入(解决TS类型警告) 1. **创建vite-env.d.ts文件** ```typescript /// <reference types="vite/client" /> declare module "*.vue" { import { DefineComponent } from "vue" const component: DefineComponent<{}, {}, any> export default component } ``` 2. **配置路径别名** ```typescript // vite.config.ts resolve: { alias: { &#39;@&#39;: path.resolve(__dirname, &#39;./src&#39;) } } ``` 此时可使用`import MyComponent from &#39;@/components/MyComponent.vue&#39;`语法[^3]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值