vue实现响应式
Vue 响应式原理
Vue 的响应式系统基于 JavaScript 的 Object.defineProperty(Vue 2)或 Proxy(Vue 3)实现,通过数据劫持和依赖追踪实现数据变化时的自动更新。
Vue 2 实现方式
Vue 2 使用 Object.defineProperty 对对象的属性进行劫持。当访问属性时收集依赖,修改属性时触发更新。
function defineReactive(obj, key, val) {
const dep = new Dep(); // 依赖管理
Object.defineProperty(obj, key, {
get() {
if (Dep.target) {
dep.addSub(Dep.target); // 收集依赖
}
return val;
},
set(newVal) {
if (newVal === val) return;
val = newVal;
dep.notify(); // 触发更新
}
});
}
Vue 3 实现方式
Vue 3 使用 Proxy 代理整个对象,可以监听动态添加的属性,并解决 Vue 2 中数组和对象的部分限制。

function reactive(obj) {
return new Proxy(obj, {
get(target, key, receiver) {
track(target, key); // 收集依赖
return Reflect.get(target, key, receiver);
},
set(target, key, value, receiver) {
const result = Reflect.set(target, key, value, receiver);
trigger(target, key); // 触发更新
return result;
}
});
}
响应式数据声明
在 Vue 组件中,可以通过以下方式声明响应式数据:
选项式 API
export default {
data() {
return {
message: 'Hello Vue!'
};
}
};
组合式 API
import { ref, reactive } from 'vue';
export default {
setup() {
const count = ref(0); // 基本类型
const state = reactive({ // 对象类型
name: 'Vue 3'
});
return { count, state };
}
};
响应式注意事项
-
对象属性添加:Vue 2 中直接添加新属性不会触发响应,需使用
Vue.set()或this.$set()。Vue 3 的Proxy无此限制。
-
数组变更检测:Vue 2 中直接通过索引修改数组或修改长度不会触发响应,需使用变异方法(如
push,pop)或Vue.set()。 -
性能优化:大型响应式对象可能影响性能,可通过
Object.freeze()冻结不需要响应式的数据。
响应式工具函数
Vue 提供了一些响应式相关的工具函数:
import {
isRef,
unref,
toRef,
toRefs,
markRaw,
shallowRef,
shallowReactive
} from 'vue';
// 创建非响应式引用
const nonReactive = markRaw({ key: 'value' });
// 浅层响应式
const shallow = shallowReactive({ nested: { data: 'value' } });






