vue怎么实现响应式
Vue 响应式原理
Vue 的响应式系统基于 JavaScript 的 Object.defineProperty(Vue 2)或 Proxy(Vue 3)实现,能够自动追踪数据变化并更新视图。
Vue 2 实现方式
Vue 2 使用 Object.defineProperty 对数据对象的属性进行劫持,通过 getter 和 setter 实现依赖收集和派发更新。

// 简化版响应式实现
function defineReactive(obj, key, val) {
Object.defineProperty(obj, key, {
get() {
console.log(`获取 ${key}: ${val}`);
return val;
},
set(newVal) {
if (newVal !== val) {
console.log(`设置 ${key} 为 ${newVal}`);
val = newVal;
// 触发视图更新
}
}
});
}
const data = { message: 'Hello' };
defineReactive(data, 'message', data.message);
data.message = 'World'; // 触发 setter
Vue 3 实现方式
Vue 3 改用 Proxy 实现响应式,能够监听整个对象而无需递归遍历属性,并支持对数组和新增属性的监听。
// 简化版 Proxy 实现
function reactive(obj) {
return new Proxy(obj, {
get(target, key) {
console.log(`获取 ${key}: ${target[key]}`);
return target[key];
},
set(target, key, value) {
if (target[key] !== value) {
console.log(`设置 ${key} 为 ${value}`);
target[key] = value;
// 触发视图更新
}
return true;
}
});
}
const data = reactive({ message: 'Hello' });
data.message = 'World'; // 触发 set
响应式数组处理
Vue 对数组方法进行了包裹,确保调用 push、pop 等方法时也能触发响应式更新。

// Vue 2 数组响应式处理
const arrayProto = Array.prototype;
const arrayMethods = Object.create(arrayProto);
['push', 'pop', 'shift'].forEach(method => {
const original = arrayProto[method];
arrayMethods[method] = function(...args) {
const result = original.apply(this, args);
// 通知更新
return result;
};
});
依赖收集与派发更新
Vue 通过 Watcher 和 Dep 实现依赖收集,当数据变化时通知所有依赖进行更新。
// 简化版依赖收集
class Dep {
constructor() {
this.subscribers = [];
}
depend() {
if (target) {
this.subscribers.push(target);
}
}
notify() {
this.subscribers.forEach(sub => sub());
}
}
let target = null;
function watchEffect(cb) {
target = cb;
cb();
target = null;
}
实际应用
在 Vue 组件中,data 返回的对象会被自动转为响应式,计算属性和 watch 也基于此系统实现。
export default {
data() {
return {
count: 0 // 自动变为响应式
}
},
methods: {
increment() {
this.count++; // 触发视图更新
}
}
}
注意事项
- 对象新增属性需要使用
Vue.set(Vue 2)或直接赋值(Vue 3) - 数组索引直接修改需要特殊处理
- 响应式系统无法追踪临时变量或未初始化的属性
Vue 的响应式系统通过数据劫持和依赖收集实现了数据与视图的自动同步,开发者只需关注数据变化,无需手动操作 DOM。






