摘要
Vue3 的响应式系统使用 Proxy 替代了 Vue2 的 Object.defineProperty,大大提升了性能和灵活性,同时提供了 reactive 和 ref 这两种方式来创建响应式数据。
# 一、Vue2 的响应式系统问题
在 Vue2 中,Vue 采用 Object.defineProperty 来拦截对象属性的读写操作,以实现数据响应式。
# Vue2 的数据劫持方式
let data = {};
Object.defineProperty(data, 'message', {
get() {
console.log('获取 message 值');
return 'Hello Vue2';
},
set(newVal) {
console.log('设置 message 值:', newVal);
}
});
data.message; // 触发 get
data.message = 'Vue2 变更'; // 触发 set
# Vue2 的问题
无法检测新加的属性
Vue2 只会在 初始化 时劫持已有属性,如果动态添加新属性,Vue 不会 监听。let obj = {}; Vue.set(obj, 'count', 1); // 需要 Vue.set 才能让新属性变成响应式数组的变更监听存在缺陷
只能监听push、pop等方法,而不能监听索引变更,如:let arr = [1, 2, 3]; arr[0] = 100; // 视图不会更新!深层嵌套对象的性能问题
Vue2 需要递归遍历整个对象,在初始化时 给每个属性 添加getter和setter,对 大对象性能影响较大。
# 二、Vue3 如何优化响应式
Vue3 使用 Proxy 代理整个对象,而不是逐个属性劫持,解决了 Vue2 的所有问题。
# Vue3 Proxy 实现响应式
let data = new Proxy({ message: 'Hello Vue3' }, {
get(target, key) {
console.log(`读取 ${key}`);
return target[key];
},
set(target, key, value) {
console.log(`设置 ${key} 为 ${value}`);
target[key] = value;
return true;
}
});
data.message; // 触发 get
data.message = 'Vue3 变更'; // 触发 set
# Vue3 Proxy 的优势
✅ 支持动态新增属性
let obj = reactive({});
obj.count = 1; // 直接赋值就能变成响应式
✅ 正确监听数组变化
let arr = reactive([1, 2, 3]);
arr[0] = 100; // 视图会更新!
✅ 性能优化 Vue3 不再需要递归遍历所有属性,而是当访问某个属性时才进行劫持,提升初始化性能。
# 三、Vue3 响应式 API
Vue3 提供了两种响应式 API:
1️⃣ reactive:适用于对象和数组
import { reactive } from 'vue';
const state = reactive({
count: 0,
info: { name: 'Vue3' }
});
state.count++; // 响应式更新
state.info.name = 'Vue3 Updated'; // 深层嵌套仍是响应式
2️⃣ ref:适用于基本数据类型
import { ref } from 'vue';
const count = ref(0);
count.value++; // 需要 .value 才能访问
✅ reactive 适用于对象,✅ ref 适用于基础类型,组合使用能实现更高效的状态管理。
# 四、Vue3 响应式在实际开发中的应用
Vue3 的响应式系统不仅提高了性能,还让代码更加简洁。在实际开发中,我们可以利用 Vue3 响应式 API 来实现 数据驱动 UI。
示例:计数器
<template>
<div>
<p>当前计数:{{ count }}</p>
<button @click="increment">增加</button>
</div>
</template>
<script setup>
import { ref } from 'vue';
const count = ref(0);
const increment = () => count.value++;
</script>
✅ 代码更简单:没有 this,也不需要 data() 和 methods,逻辑更直观!
# 结论
| 版本 | 响应式方式 | 监听对象新增属性 | 监听数组索引 | 初始化性能 |
|---|---|---|---|---|
| Vue2 | Object.defineProperty | ❌ 需要 Vue.set | ❌ 不支持 | ❌ 递归所有属性 |
| Vue3 | Proxy | ✅ 支持 | ✅ 支持 | ✅ 访问时才劫持 |
Vue3 通过 Proxy 重构了响应式系统,提供了 reactive 和 ref API,解决了 Vue2 的局限性,使得数据管理更简单,推荐在新项目中优先使用。