Proxy通过创建对象代理层拦截所有操作,天然支持新增/删除属性、数组索引修改及嵌套对象懒响应,无需Object.defineProperty的递归遍历和补丁式处理。

Vue.js 3.0 放弃 Object.defineProperty,转而用 Proxy 实现响应式,核心在于它能自然、完整地拦截对象的各类操作,无需手动遍历、递归或打补丁。
Proxy 是怎么接管属性访问的
Proxy 不是对单个属性“打补丁”,而是为整个对象创建一个代理层。所有读写操作(包括取值、赋值、新增、删除、遍历)都必须经过这个代理,因此天然覆盖动态场景。
- 创建方式:const proxy = new Proxy(target, handler),target 是原始对象,handler 是拦截规则集合
- 关键拦截器:get 拦截读取(如 obj.name、obj[0]),set 拦截赋值(如 obj.age = 25),deleteProperty 拦截 delete obj.key,ownKeys 拦截 Object.keys() 或 for...in
- 注意:必须对 proxy 实例操作才生效,直接操作 target 不会触发拦截
为什么 Proxy 能解决 Vue2 的痛点
Object.defineProperty 需要预先声明所有属性,且无法监听新增/删除属性、数组索引变化、length 修改等。Proxy 则把这些都纳入拦截范围,无需额外 hack。
递归分析 Vue 项目组件依赖,从入口文件生成组件层级图,支持 Vue 2/3,输出组件名、文件路径和属性。适用于分析组件结构、排查依赖或了解项目架构。
- 动态添加属性:proxy.newKey = 'hello' → 触发 set,自动建立响应式连接
- 删除属性:delete proxy.existingKey → 触发 deleteProperty,可同步清理依赖
- 数组操作:proxy[0] = 'a' 或 proxy.length = 2 → get/set 都能捕获,不再依赖重写 push/splice 等方法
- 嵌套对象:get 拦截中对返回值调用 reactive,实现“访问时递进响应化”,避免一次性深度遍历
响应式系统如何联动更新
Proxy 只负责“监听”,真正驱动视图更新的是依赖收集与触发机制。Vue3 把这套逻辑封装在 effect / track / trigger 三个核心函数中。
立即学习“前端免费学习笔记(深入)”;
- effect:包装副作用函数(比如渲染函数),执行时会激活 track
- track:在 get 拦截中被调用,把当前 effect 记录为该属性的依赖
- trigger:在 set/delete 等拦截中被调用,通知对应属性的所有 effect 重新执行
- ref、reactive、computed 底层都基于这一套机制,只是封装形式不同
实际开发中要注意什么
Proxy 能力强大,但使用时有几点容易忽略:
- Proxy 返回的是新对象,原对象不变;不能对普通对象直接赋值,应始终操作 reactive() 返回的代理对象
- 严格模式下,set 拦截器必须显式 return true,否则赋值失败(Vue3 内部已处理)
- Map/Set 等内置类型需用 reactive 包裹,Proxy 默认不代理它们的内部方法(如 map.set()),Vue3 通过特殊 handler 支持
- 非响应式数据(如 Date、RegExp、Promise)不会被 reactive 处理,需用 ref 或手动转换

















