vue响应式怎么实现
Vue 响应式实现原理
Vue 的响应式系统通过数据劫持和依赖收集实现。核心是利用 JavaScript 的 Object.defineProperty(Vue 2.x)或 Proxy(Vue 3.x)来监听数据变化。
Vue 2.x 实现方式
Vue 2.x 使用 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 = { count: 0 };
defineReactive(data, 'count', data.count);
Vue 3.x 实现方式
Vue 3.x 使用 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({ count: 0 });
依赖收集与派发更新
Vue 通过依赖收集跟踪数据变化时的更新操作。每个响应式属性关联一个依赖管理器(Dep),当属性被访问时收集依赖(Watcher),属性变化时通知依赖更新。
class Dep {
constructor() {
this.subscribers = new Set();
}
depend() {
if (activeUpdate) {
this.subscribers.add(activeUpdate);
}
}
notify() {
this.subscribers.forEach(sub => sub());
}
}
let activeUpdate = null;
function observe(obj) {
Object.keys(obj).forEach(key => {
let internalValue = obj[key];
const dep = new Dep();
Object.defineProperty(obj, key, {
get() {
dep.depend();
return internalValue;
},
set(newVal) {
if (internalValue !== newVal) {
internalValue = newVal;
dep.notify();
}
}
});
});
}
数组的响应式处理
Vue 对数组方法(如 push、pop 等)进行重写,使其能够触发视图更新。
const arrayProto = Array.prototype;
const arrayMethods = Object.create(arrayProto);
['push', 'pop', 'shift', 'unshift'].forEach(method => {
const original = arrayProto[method];
arrayMethods[method] = function(...args) {
const result = original.apply(this, args);
console.log(`数组 ${method} 操作`);
return result;
};
});
function observeArray(arr) {
arr.__proto__ = arrayMethods;
}
响应式系统的局限性
某些情况下需要特殊处理:

- 对象新增属性需要使用
Vue.set或this.$set - 数组直接通过索引修改元素需要使用
Vue.set - 对于大数组或复杂对象,响应式可能带来性能问题
Vue 3.x 的 Proxy 实现解决了大部分 Vue 2.x 的局限性,提供了更完善的响应式能力。






