Vue3的Proxy解决了多少Vue2中defineProperty解决不了的问题?

举报
watermelo37 发表于 2025/06/30 22:03:34 2025/06/30
【摘要】         作者:watermelo37        CSDN万粉博主、华为云云享专家、阿里云专家博主、腾讯云、支付宝合作作者,全平台博客昵称watermelo37。        一个假装是giser的coder,做不只专注于业务逻辑的前端工程师,Java、Docker、Python、LLM均有涉猎。------------------------------------------...

        作者:watermelo37

        CSDN万粉博主、华为云云享专家、阿里云专家博主、腾讯云、支付宝合作作者,全平台博客昵称watermelo37。

        一个假装是giser的coder,做不只专注于业务逻辑的前端工程师,Java、Docker、Python、LLM均有涉猎。


---------------------------------------------------------------------

温柔地对待温柔的人,包容的三观就是最大的温柔。

---------------------------------------------------------------------

Vue3的Proxy解决了多少Vue2中defineProperty解决不了的问题?


        Vue2通过defineProperty来实现数据劫持,也就是响应式交互的基础,但是defineProperty限于自身逻辑,在引用类型中有些情况无法被监听到,比如深层对象的变化、直接通过索引修改数组元素等。

        在 Vue3 发布时,Proxy 的引入被称为“技术底座的大革新”。相比 Vue2 使用的 Object.defineProperty,Proxy 带来了巨大的功能提升与开发体验优化。

        那 Vue3 的 Proxy 解决了哪些 Vue2 中 defineProperty 解决不了的问题呢?

一、Vue2 使用 defineProperty 的机制


        在 Vue2 中,响应式系统是通过 Object.defineProperty 实现的,每个属性都通过 getter/setter 被拦截,从而实现依赖追踪和变更通知:

Object.defineProperty(obj, 'key', {
  get() {
    // 收集依赖
    return value;
  },
  set(newVal) {
    // 通知更新
    value = newVal;
  }
});

        但defineProperty 有天然的缺陷:

问题 说明
1. 无法监听新增属性 给对象新增的属性不会自动响应,需要 Vue.set
2. 无法监听删除属性 删除属性也不会触发更新,需要手动触发。
3. 无法直接监听数组索引变化 修改数组索引无法被侦测,需要使用特定方法(如 Vue.set)。
4. 无法拦截整个对象 只能一开始递归遍历每一个属性,无法整体拦截对象。
5. 性能问题(大量数据) 初始化时递归地遍历所有对象属性,成本很高。

         为了弥补这些问题,会出现如Vue.set、Vue.delete这些方法来实现对新增和删除属性的监听,没办法,defineProperty从底层上就有这些限制,尤雨溪本人来也解决不了。


二、Proxy 解决了哪些 Vue2 时代的问题?


        来,咱们一一对应看。

1、新增属性能自动响应

        Vue2问题:

vm.obj.a = 123;  // 不会响应式更新,必须 Vue.set(vm.obj, 'a', 123);

        Vue3解决:

reactiveObj.a = 123; // 自动响应,无需手动 set!

        因为 Proxy 能拦截 set 操作,即使属性原本不存在,也能监听到。

2、删除属性也能触发响应

        Vue2问题:

delete vm.obj.a; // 删除了但不会通知视图更新

        Vue3解决:

delete reactiveObj.a; // 自动触发响应,页面同步更新!

        因为 Proxy 支持拦截 deleteProperty 操作,天然监听删除。

3、数组索引可以被正确追踪

        Vue2问题:

vm.arr[2] = 10; // 不会响应,需要用 Vue.set(vm.arr, 2, 10)

        Vue3解决:

reactiveArr[2] = 10; // 自动触发响应,刷新视图!

        因为 Proxy 能拦截数组下标访问和修改,索引不再是问题。

4、不再需要递归遍历属性

        Vue2问题:

        初始化时,需要递归 walk 整棵数据树,开销大,尤其是深层嵌套对象或大数组时,性能堪忧。

        Vue3解决:

        只要一层 Proxy,就可以懒代理,当访问到某个子对象时,再进行子对象的代理(懒代理 Lazy Proxy)。

5、更好支持 Map、Set、WeakMap

Vue2问题:

  • defineProperty  只能拦截对象的属性,无法拦截 Map、Set 的操作。

  • Vue2基本放弃了对这些复杂结构的响应式支持。

Vue3解决:

  • Proxy 可以拦截.get()、.set()、.add()、.delete()等各种方法。

  • 因此,Vue3 内置了对 Map、Set 的响应式支持!

import { reactive } from 'vue';

const map = reactive(new Map());
map.set('key', 'value'); // 响应式


三、结语


        可以说,Proxy 是 Vue3 响应式革命的基石。Vue3 用 Proxy,完美解决了 Vue2 中 defineProperty 无法监听“新增属性、删除属性、数组索引、复杂数据结构”等一系列痛点,同时带来了更高效、更优雅、更强大的响应式体验。

        只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。