news 2026/4/16 16:20:35

Vue技术——JavaScript 数据代理的实现与应用

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Vue技术——JavaScript 数据代理的实现与应用

Vue 中的“数据代理”(Data Proxy)实现与应用详解

在 Vue(尤其是 Vue 2)中,数据代理数据劫持/响应式是两个密切相关但又不同的概念。很多人把它们混在一起,今天我们彻底拆开来讲清楚。

1. 什么是“数据代理”?(Vue 2 & Vue 3 通用概念)

数据代理:让vm(Vue 实例)直接代理访问data对象里的属性。

写法对比:

// Vue 2 / Vue 3 都支持这种写法constvm=newVue({data:{msg:"hello",user:{name:"重阳"}}})// 不用写 vm.$data.msgconsole.log(vm.msg)// hello ← 代理后直接访问vm.msg="hi"// 也能直接修改

没有数据代理时的写法(原始):

console.log(vm.$data.msg)// 麻烦vm.$data.msg="hi"

核心目的:让开发者书写更简洁、自然,像操作普通对象一样操作 Vue 实例。

2.Vue 2 中的数据代理实现(Object.defineProperty + 循环)

Vue 2 在_initData阶段做了两件事:

  1. 数据劫持(响应式):用Object.definePropertydata每个属性改造成带 getter/setter 的
  2. 数据代理:把data的每个 key 代理到vm实例上

简化核心代码(伪代码风格):

functioninitData(vm){constdata=vm.$options.data.call(vm)// 执行 data 函数得到对象vm._data=data// 内部保存一份// 第一步:数据代理(让 vm.msg → vm._data.msg)for(letkeyindata){proxy(vm,'_data',key)}// 第二步:响应式劫持(observe)observe(data)}// 代理函数(最核心的三行)functionproxy(target,sourceKey,key){Object.defineProperty(target,key,{enumerable:true,configurable:true,get(){returnthis[sourceKey][key]// vm.msg → vm._data.msg},set(newVal){this[sourceKey][key]=newVal// vm.msg = xx → vm._data.msg = xx}})}

结论:Vue 2 的数据代理本质是用Object.defineProperty在 Vue 实例上为每个 data 属性定义了 getter/setter,只是不做依赖收集,只做转发。

3. Vue 3 中的数据代理(Proxy 时代的变化)

Vue 3 完全抛弃了Object.defineProperty的属性级劫持,改用Proxy代理整个对象

但“数据代理”这个概念依然存在,只是实现方式变了。

Vue 3 源码中(简化):

// reactive 函数返回的就是代理对象exportfunctionreactive<Textendsobject>(target:T):T{returncreateReactiveObject(target,...)}constreactiveMap=newWeakMap()functioncreateReactiveObject(target){// ... 省略边界判断constproxy=newProxy(target,{get(target,key,receiver){// 1. 依赖收集 track()track(target,key)constres=Reflect.get(target,key,receiver)// 如果是对象,继续代理(深度响应式)if(isObject(res)){returnreactive(res)// 惰性代理}returnres},set(target,key,value,receiver){constoldValue=Reflect.get(target,key,receiver)constresult=Reflect.set(target,key,value,receiver)// 2. 触发更新 trigger()if(oldValue!==value){trigger(target,key)}returnresult},// deleteProperty、has、ownKeys 等也都有拦截})reactiveMap.set(target,proxy)returnproxy}

Vue 3 里“数据代理”体现在哪里?

setup/ref/reactive返回的对象,最终挂载到组件实例proxyRefs/setupState上时,也做了类似代理,让this.msg可以直接访问setup返回的属性。

但更常见的是:开发者直接使用 reactive 返回的 proxy 对象,不再需要额外的“代理到 vm”这一步。

4. Vue 2 vs Vue 3 数据代理 & 响应式对比(面试必背表)

维度Vue 2 (Object.defineProperty)Vue 3 (Proxy)胜出方
劫持粒度属性级(必须先遍历 data)对象级(一次 Proxy 搞定整个对象)Vue 3
新增属性响应式不支持(需 Vue.set / this.$set)天然支持Vue 3
删除属性响应式不支持支持(deleteProperty 拦截)Vue 3
数组变化(push 等)需要重写 7 个数组方法直接拦截,无需重写Vue 3
嵌套对象响应式递归遍历所有属性(性能开销大)惰性递归(访问到才代理)Vue 3
性能(大数据对象)遍历 + 定义 getter/setter 开销大Proxy 创建快,拦截统一Vue 3
数据代理实现显式在 vm 上 defineProperty 转发基本不需要额外代理层(直接用 proxy 对象)Vue 3 更简洁
兼容性IE9+ES6+(现代浏览器)Vue 2

5. 手写极简版 Vue 数据代理(Vue 2 风格 + Vue 3 风格)

Vue 2 风格(数据代理 + 简单响应式)

classMiniVue{constructor(options){this.$data=options.data()this.initProxy()// 简单观察者(实际 Vue 复杂得多)this.observe(this.$data)}initProxy(){Object.keys(this.$data).forEach(key=>{Object.defineProperty(this,key,{get:()=>this.$data[key],set:val=>{this.$data[key]=val;console.log(`${key}更新了!`)}})})}observe(obj){Object.keys(obj).forEach(key=>{letval=obj[key]Object.defineProperty(obj,key,{get:()=>val,set:newVal=>{val=newVal;console.log('数据劫持更新')}})})}}constapp=newMiniVue({data(){return{count:0}}})app.count=100// 触发代理 set + 数据劫持 set

Vue 3 风格(直接用 Proxy)

functionreactive(obj){returnnewProxy(obj,{set(target,key,val){console.log(`${key}被修改为${val}`)target[key]=val// 这里会 trigger 更新视图returntrue}})}conststate=reactive({count:0,user:{name:'重阳'}})state.count=999// 拦截state.user.name='重阳666'// 惰性代理后也能拦截

总结一句话

重阳,你现在用的是 Vue 2 还是 Vue 3 项目?
想继续深挖:

随时告诉我,我们继续拆!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/15 22:23:56

【小程序毕设全套源码+文档】基于微信小程序django咖啡博物馆预约小程序的设计与实现(丰富项目+远程调试+讲解+定制)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/4/16 13:05:52

可编辑PPT | 数据治理与标准推动数据成为“金矿”

一、工业互联网与数据中台 PPT强调了智能制造的核心要素是数据、模型和知识&#xff0c;这些要素共同构成了智能工厂的基础。智能工厂的构建涉及业务模型的构建、仿真预测和智能决策等方面&#xff0c;以实现生产过程的自动化和优化。 工业互联网架构则着重于数据的利用&#…

作者头像 李华
网站建设 2026/4/16 10:51:27

强烈安利8个降AIGC网站,千笔AI帮你轻松降AI率

AI降重工具&#xff1a;让论文更自然&#xff0c;更安心 在当前的学术环境中&#xff0c;越来越多的高校和期刊开始使用AIGC检测系统来识别AI生成内容。对于本科生来说&#xff0c;这无疑增加了论文写作的难度。如何在保持原意不变的前提下&#xff0c;有效降低AI痕迹和查重率&…

作者头像 李华
网站建设 2026/4/16 12:59:46

嵌入式C++教程——ETL(Embedded Template Library)

嵌入式C教程——ETL&#xff08;Embedded Template Library&#xff09; 好奇心&#xff1a;为什么在嵌入式世界里&#xff0c;总有人把 new 当成“危险品”而随身带手套&#xff1f;答案很简单&#xff1a;堆是不可预测的。ETL&#xff08;Embedded Template Library&#xf…

作者头像 李华