在 Vue 2 中,Dep.target
主要用于收集依赖和触发依赖更新。Vue 的响应式系统使用了基于观察者模式的设计,其中有三个核心概念:Observer
、Dep
(Dependency)和 Watcher
。
-
Observer(观察者):负责将对象转化为响应式对象,即监听对象属性的变化。
-
Dep(Dependency) :用于收集依赖,每个响应式对象上都有一个对应的
Dep
对象,其中存储了所有依赖于该对象的Watcher
。 -
Watcher(观察者) :负责创建视图和更新视图的逻辑,当依赖的数据发生变化时,
Watcher
负责触发更新。
Dep.target
在这个机制中充当全局唯一的标志,用来指示当前正在进行依赖收集的 Watcher
。在 Watcher
初始化过程中,会将 Dep.target
设置为当前 Watcher
,然后触发数据的读取操作。当读取数据时,Observer
会检测当前是否有正在进行依赖收集的 Watcher
(即 Dep.target
是否存在),如果有,就将该 Watcher
添加到当前属性对应的 Dep
中。
为什么要这样设计呢?
-
精确定位依赖关系 :通过
Dep.target
的设置,可以精确地知道是哪个Watcher
正在进行依赖收集。这样,每个属性的依赖关系都可以被精确地管理,避免不必要的更新。 -
自动依赖收集:由于 JavaScript 是单线程的,通过在读取数据时收集依赖,可以自动追踪数据的变化,从而触发视图的更新。这样,开发者无需手动管理依赖关系,系统可以自动进行依赖追踪。
示例代码可能如下所示:
javascript
// Dep 类用于收集依赖
class Dep {
constructor() {
this.subscribers = [];
}
// 添加依赖
depend() {
if (Dep.target && !this.subscribers.includes(Dep.target)) {
this.subscribers.push(Dep.target);
}
}
// 通知依赖更新
notify() {
this.subscribers.forEach(sub => sub.update());
}
}
// Dep.target 用于指示当前的 Watcher
Dep.target = null;
// Watcher 类负责创建视图和更新视图的逻辑
class Watcher {
constructor() {
// 设置 Dep.target 为当前 Watcher
Dep.target = this;
// 在读取数据时,会触发依赖收集
this.value = data.someProperty;
// 重置 Dep.target
Dep.target = null;
}
// 更新视图的逻辑
update() {
// 实现更新的逻辑
}
}
// Observer 类负责将对象转化为响应式对象
class Observer {
constructor(data) {
this.data = data;
this.observe(data);
}
observe(data) {
Object.keys(data).forEach(key => {
let dep = new Dep();
let val = data[key];
Object.defineProperty(data, key, {
get() {
dep.depend(); // 在读取数据时收集依赖
return val;
},
set(newVal) {
if (val !== newVal) {
val = newVal;
dep.notify(); // 在数据变化时通知依赖更新
}
}
});
});
}
}
// 示例数据
const data = {
someProperty: 42
};
// 创建 Observer 实例,实现响应式
const observer = new Observer(data);
// 创建 Watcher 实例,用于更新视图
const watcher = new Watcher();
在这个简化的示例中,Dep.target
的设置和重置使得在读取数据时能够正确地收集依赖。这种机制使得 Vue 能够实现高效的响应式更新。