在 Vue3 中,数据代理主要通过 ES6 的Proxy实现响应式系统,相比 Vue2 的Object.defineProperty,Proxy 能更高效、全面地拦截对象操作。以下是 Vue3 实现数据代理的核心原理和关键步骤:
一、核心原理:Proxy 的响应式拦截
Vue3 通过Proxy对目标对象(如组件的data、props)进行包裹,当对象的属性被读取或修改时,触发 Proxy 的拦截器,从而实现:
- 依赖收集:记录哪些副作用函数(如渲染函数)依赖了该属性。
- 更新通知:当属性变化时,通知所有依赖它的副作用函数重新执行(更新视图)。
二、实现数据代理的关键步骤
1. 创建响应式对象:reactive与proxy
Vue3 通过reactive函数创建响应式代理,其内部核心逻辑如下(简化版):
js
import { reactive } from 'vue'
// 1. 核心函数:创建Proxy代理
function createReactiveProxy(target) {
// 处理非对象类型(如字符串、数字),直接返回原值(Vue3通过toRaw判断)
if (!isObject(target)) return target
// 2. 创建Proxy实例,定义拦截器
const proxy = new Proxy(target, {
// 读取属性时触发依赖收集
get(target, key) {
// 收集当前副作用函数(如渲染函数)的依赖
track(target, key)
return Reflect.get(target, key)
},
// 设置属性时触发更新通知
set(target, key, value) {
const oldValue = target[key]
const result = Reflect.set(target, key, value)
// 如果值变化,通知所有依赖该属性的副作用函数更新
if (oldValue !== value) {
trigger(target, key)
}
return result
},
// 其他拦截器(如删除属性、判断属性存在等)
deleteProperty(target, key) {
const result = Reflect.deleteProperty(target, key)
trigger(target, key, 'delete')
return result
}
})
return proxy
}
// 3. 对外暴露的reactive函数
export function reactive(target) {
return createReactiveProxy(target)
}
2. 依赖收集与更新通知:track与trigger
track函数:当属性被读取时,将当前激活的副作用函数(通过activeEffect记录)存入该属性的依赖集合中。trigger函数:当属性被修改时,取出依赖集合中的所有副作用函数并执行,触发视图更新。
三、Vue3 响应式系统的优化机制
-
懒代理(Lazy Proxy)
- 不再像 Vue2 那样递归遍历对象所有属性,而是在访问属性时按需创建代理,减少初始化开销。
- 例如:
obj.a.b.c只有在访问到c时才会为b创建代理,提升大型对象的处理效率。
-
深层响应式与浅层响应式
- 深层响应式:默认通过 Proxy 递归处理嵌套对象,但可通过
shallowReactive创建浅层代理(仅第一层响应式)。 - 浅层响应式:适用于已知结构的对象,避免不必要的深层代理开销。
- 深层响应式:默认通过 Proxy 递归处理嵌套对象,但可通过
-
Ref 与 Reactive 的区别
reactive用于代理对象,ref用于包装基本类型(如ref(0)),内部通过value属性实现响应式:js
const count = ref(0) // 读取:count.value,修改:count.value = 1ref在对象中会自动解包(如obj.count直接访问value),简化基本类型的响应式处理。
四、在组件中的实际应用
vue
<template>
<div>{{ state.count }}</div>
<button @click="state.count++">+1</button>
</template>
<script>
import { reactive } from 'vue'
export default {
setup() {
// 1. 创建响应式状态
const state = reactive({
count: 0,
list: [1, 2, 3]
})
// 2. 无需返回this,直接返回需要暴露的属性
return {
state
}
}
}
</script>
- 当点击按钮修改
state.count时,Proxy 的set拦截器触发trigger,通知组件重新渲染。 - 数组
state.list的push、splice等操作会被 Proxy 原生拦截,自动触发更新。
总结:Vue3 数据代理的核心优势
- 更全面的拦截能力:支持数组操作、动态属性、删除属性等,无需手动封装。
- 更高的性能:懒代理机制减少初始化开销,深层对象处理更高效。
- 更简洁的实现:无需递归遍历属性,代码结构更清晰(如
reactive与ref的配合)。
通过 Proxy 的响应式代理,Vue3 实现了更灵活、高效的响应式系统,尤其适合大型项目中复杂数据结构的管理。

被折叠的 条评论
为什么被折叠?



