Vue实现数据响应式
Vue 数据响应式原理
Vue 的数据响应式是通过 数据劫持 结合 发布-订阅模式 实现的,核心是利用 Object.defineProperty(Vue 2.x)或 Proxy(Vue 3.x)来监听数据变化。
Vue 2.x 实现方式
使用 Object.defineProperty
Vue 2.x 通过 Object.defineProperty 递归地将数据对象的属性转换为 getter/setter,从而在属性被访问或修改时触发更新。
function defineReactive(obj, key, val) {
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function() {
console.log(`获取 ${key}: ${val}`);
return val;
},
set: function(newVal) {
if (newVal !== val) {
console.log(`设置 ${key}: ${newVal}`);
val = newVal;
// 触发视图更新
}
}
});
}
const data = { name: 'Vue' };
defineReactive(data, 'name', data.name);
data.name = 'React'; // 触发 setter
数组的特殊处理
Vue 2.x 无法直接监听数组索引变化,因此重写了数组的 push、pop、shift、unshift、splice、sort、reverse 方法,在调用这些方法时触发更新。

const arrayProto = Array.prototype;
const arrayMethods = Object.create(arrayProto);
['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'].forEach(method => {
const original = arrayProto[method];
arrayMethods[method] = function(...args) {
const result = original.apply(this, args);
console.log(`数组方法 ${method} 被调用`);
// 触发视图更新
return result;
};
});
Vue 3.x 实现方式
使用 Proxy
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({ name: 'Vue' });
data.name = 'React'; // 触发 set
响应式工具函数
Vue 3.x 提供了 reactive(对象)和 ref(基本类型)等 API:

import { reactive, ref } from 'vue';
const state = reactive({ count: 0 });
const num = ref(1);
state.count++; // 自动触发更新
num.value++; // 通过 .value 访问
依赖收集与派发更新
依赖收集(Dep)
在 getter 中收集依赖(Watcher),在 setter 中通知依赖更新。
class Dep {
constructor() {
this.subscribers = new Set();
}
depend() {
if (currentWatcher) {
this.subscribers.add(currentWatcher);
}
}
notify() {
this.subscribers.forEach(watcher => watcher.update());
}
}
观察者(Watcher)
每个组件实例对应一个 Watcher,负责更新视图。
class Watcher {
constructor(updateFn) {
this.updateFn = updateFn;
this.update();
}
update() {
currentWatcher = this;
this.updateFn();
currentWatcher = null;
}
}
总结
- Vue 2.x:通过
Object.defineProperty监听对象属性,重写数组方法。 - Vue 3.x:通过
Proxy实现全面监听,支持对象和数组。 - 核心流程:数据劫持 → 依赖收集 → 派发更新 → 视图渲染。






