Vue 3 使用 Proxy 替代 Object.defineProperty 实现响应式,解决了动态增删属性、数组索引和 length 变化、非对象类型代理及嵌套结构性能等问题,并提供更语义化、可扩展的拦截能力。

Vue 3 放弃了 Vue 2 中基于 Object.defineProperty 的响应式实现,转而使用 Proxy 构造函数。这不是简单的技术升级,而是为从根本上解决旧机制的固有缺陷。
无法监听对象属性的动态增删
Object.defineProperty 只能对已存在的属性进行劫持,新增或删除属性时不会触发响应更新。例如:
data = { a: 1 }
Vue.set(data, 'b', 2) // 必须用 Vue.set 才能响应
delete data.a // 视图不会自动更新
Proxy 拦截的是整个对象的操作,天然支持 set、deleteProperty 等 trap,新增/删除属性无需额外 API,直接赋值或 delete 即可触发依赖收集与更新。
立即学习“前端免费学习笔记(深入)”;
无法监听数组索引和 length 变化
Vue 2 中对数组做了特殊处理(重写 push/pop 等 7 个方法),但依然无法响应 arr[0] = newVal 或 arr.length = 0 这类操作。
Vue 3 组合式 API 与 最佳实践,涵盖代码组织、useXxx 模式、组合式函数设计、Store 集成、响应式优化及功能抽取。
Proxy 可以拦截 set 操作,无论目标是对象属性还是数组索引,只要写入就会被捕获。同时还能监听 length 修改、数组清空等所有底层变更,真正实现“无死角”响应。
无法代理非对象类型与嵌套结构限制
Object.defineProperty 只能作用于对象,对 Map、Set、Date、RegExp 等原生类型束手无策;且对多层嵌套对象,必须逐层递归定义,性能差、易遗漏。
Proxy 可代理任意对象(包括 Map、Set),配合懒代理策略(仅在访问时递归代理深层属性),既支持丰富数据结构,又避免初始化时的性能开销。比如:
– reactive(new Map([['key', 'val']])) 直接响应
– obj.nested?.prop 访问时才代理 nested,不浪费资源
更语义化、可扩展的拦截能力
Proxy 提供 13 种 trap(如 has、ownKeys、getOwnPropertyDescriptor),让响应式系统可以精确控制行为。例如:
-
has拦截in操作,使'x' in reactiveObj正确响应 -
ownKeys拦截Object.keys()和for...in,确保遍历结果与响应一致 - 结合
Reflect实现透明转发,保持原生行为不被破坏
这些能力让 Vue 3 的响应式不仅更健壮,也为未来支持更多语言特性(如 Proxy-based reactive primitives)打下基础。

















