vue怎么实现数据检测
Vue 数据检测的实现方式
Vue 的数据检测主要通过响应式系统实现,核心是利用 JavaScript 的 Object.defineProperty 或 ES6 的 Proxy 来劫持数据的变化,并在数据变化时通知依赖的视图进行更新。
使用 Object.defineProperty 实现响应式
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 = {};
defineReactive(data, 'message', 'Hello Vue');
data.message; // 输出: 获取 message: Hello Vue
data.message = 'Hello World'; // 输出: 设置 message: Hello World
使用 Proxy 实现响应式
Vue 3.x 使用 Proxy 替代 Object.defineProperty,能够监听整个对象而无需递归遍历属性,且支持数组的监听。
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 Vue' });
data.message; // 输出: 获取 message: Hello Vue
data.message = 'Hello World'; // 输出: 设置 message: Hello World
数组的响应式处理
Vue 对数组的方法(如 push、pop、splice 等)进行了重写,以触发视图更新。
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;
};
});
const arr = [];
arr.__proto__ = arrayMethods;
arr.push(1); // 输出: 数组方法 push 被调用
依赖收集与派发更新
Vue 通过 Dep 和 Watcher 实现依赖收集和派发更新。
class Dep {
constructor() {
this.subscribers = new Set();
}
depend() {
if (currentWatcher) {
this.subscribers.add(currentWatcher);
}
}
notify() {
this.subscribers.forEach(watcher => watcher.update());
}
}
let currentWatcher = null;
class Watcher {
constructor(updateFn) {
this.updateFn = updateFn;
this.update();
}
update() {
currentWatcher = this;
this.updateFn();
currentWatcher = null;
}
}
const dep = new Dep();
new Watcher(() => {
dep.depend();
console.log('视图更新');
});
dep.notify(); // 输出: 视图更新
使用 Vue 的 API 实现数据检测
Vue 提供了 Vue.set 和 Vue.delete 方法,用于在动态添加或删除属性时触发响应式更新。
Vue.set(data, 'newKey', 'newValue');
Vue.delete(data, 'oldKey');
总结
Vue 的数据检测机制通过以下方式实现:
- 使用
Object.defineProperty或Proxy劫持数据的变化。 - 通过依赖收集(
Dep和Watcher)在数据变化时通知视图更新。 - 对数组方法进行重写以支持数组的响应式变化。
- 提供
Vue.set和Vue.delete处理动态属性的响应式更新。







