Vue.js是一个渐进式JavaScript框架,用于构建用户界面。其核心特性之一是响应式系统,它能够自动追踪数据的变化并更新DOM,从而实现了数据绑定和动态更新视图的效果。本文将深入探讨Vue.js响应式系统的原理与实现。
Vue.js的响应式系统基于以下几个核心概念:
Vue.js在2.x版本中主要使用`Object.defineProperty`来拦截对象属性的getter和setter。而在3.x版本中,Vue.js引入了`Proxy`对象,提供了更灵活和强大的数据劫持能力。
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) {
val = newVal;
dep.notify();
}
}
});
}
class Dep {
constructor() {
this.subs = [];
}
addSub(sub) {
this.subs.push(sub);
}
notify() {
this.subs.forEach(sub => sub.update());
}
}
Dep.target = null;
function watch(obj, key, callback) {
Dep.target = new Watcher(obj, key, callback);
Dep.target[key]; // 触发getter,将Watcher添加到依赖
Dep.target = null;
}
class Watcher {
constructor(obj, key, cb) {
this.obj = obj;
this.key = key;
this.cb = cb;
this.value = obj[key];
}
update() {
const newVal = this.obj[this.key];
if (newVal !== this.value) {
this.value = newVal;
this.cb(newVal);
}
}
}
const data = { message: 'Hello Vue!' };
defineReactive(data, 'message', data.message);
watch(data, 'message', (newVal) => {
console.log(`message changed to: ${newVal}`);
});
data.message = 'Hello World!'; // 控制台输出: message changed to: Hello World!
在Vue.js中,当组件渲染或计算属性被计算时,会访问响应式数据。此时,响应式系统会将这些依赖(Watcher对象)记录下来,以便在数据变化时通知它们。
当响应式数据被修改时,之前记录的依赖(Watcher对象)会被通知,并触发相应的更新逻辑。这些更新逻辑可能包括重新渲染组件或重新计算计算属性。