Vue 3 的响应式系统基于 Proxy
对象实现,具有更高的性能和灵活性,相比 Vue 2 使用的 Object.defineProperty
有明显的改进。以下是 Vue 3 响应式原理的关键部分:
1. 核心机制
Vue 3 响应式系统的核心是 reactive
API,它使用 Proxy
拦截对对象的访问和修改,从而实现数据的追踪和更新。
1.1 reactive
的实现
import { reactive } from 'vue';const state = reactive({count: 0,info: {name: 'Vue',version: 3}
});
在上述代码中:
reactive
会将传入的普通对象转换为响应式对象。- Vue 通过
Proxy
拦截对对象的操作(如get
、set
),从而实现依赖收集和变化通知。
1.2 依赖收集与追踪
响应式系统的工作过程可以分为以下几步:
- 依赖收集:当某个响应式属性被访问时,Vue 会记录哪个组件或函数依赖了该属性。
- 触发更新:当响应式属性的值发生变化时,Vue 通知所有依赖该属性的函数重新执行。
依赖收集是通过 Effect 函数 实现的:
import { effect } from 'vue';effect(() => {console.log(state.count);
});
在执行 effect
时,Vue 会自动订阅 state.count
,因此当 state.count
的值发生变化时,该 effect
会重新运行。
2. Proxy
的核心拦截点
Vue 3 的响应式系统通过 Proxy
提供的拦截机制,完成以下操作:
2.1 get
:读取属性
当访问对象的属性时,Vue 会触发 get
拦截器,从而完成依赖收集:
const handler = {get(target, key, receiver) {const result = Reflect.get(target, key, receiver);console.log(`读取属性 ${key}: ${result}`);return result;}
};
2.2 set
:修改属性
当修改对象的属性时,Vue 会触发 set
拦截器,从而通知依赖更新:
const handler = {set(target, key, value, receiver) {const result = Reflect.set(target, key, value, receiver);console.log(`设置属性 ${key}: ${value}`);// 触发依赖更新return result;}
};
2.3 track
和 trigger
Vue 3 将依赖追踪和触发分成了两个步骤:
track
:在get
中调用,用于记录依赖。trigger
:在set
中调用,用于通知依赖更新。
3. 响应式工具
Vue 3 提供了一些内置工具和方法,帮助开发者处理响应式对象。
3.1 reactive
和 ref
reactive
:将对象或数组转换为响应式对象。ref
:用于包装单个值,使其具有响应式能力。
import { ref } from 'vue';const count = ref(0);effect(() => {console.log(count.value); // 监听 count 的变化
});
count.value++; // 触发更新
3.2 computed
computed
用于创建基于响应式数据的派生状态,并具有缓存功能。
import { computed } from 'vue';const doubled = computed(() => count.value * 2);
console.log(doubled.value); // 自动计算并缓存结果
4. 与 Vue 2 的对比
特性 | Vue 2 (Object.defineProperty ) | Vue 3 (Proxy ) |
---|---|---|
支持的数据类型 | 仅支持对象和数组 | 支持对象、数组、Map、Set 等多种类型 |
深度响应式 | 初始化时递归遍历对象 | 按需追踪,性能更优 |
新增/删除属性响应式 | 需要 Vue.set 或 Vue.delete | 原生支持 |
性能 | 初始化开销较大,动态追踪效率低 | 初始化开销小,动态追踪效率高 |
5. 总结
Vue 3 的响应式系统使用 Proxy
和优化的依赖追踪机制(track
、trigger
),实现了:
- 更灵活的响应式能力(支持 Map、Set 等)。
- 更高的性能(按需追踪,避免冗余计算)。
- 更简洁的 API(无需手动处理新增/删除属性)。