class Watcher {
constructor(target, key, cb) {
Dep.targetWatcher = this;
this.cb = cb;
this.value = this.get(target, key);
Dep.targetWatcher = null;
}
get(target, key) {
return target[key];
}
run() {
this.cb();
}
}
class Dep {
constructor() {
this.subs = [];
}
addDep(watcher) {
this.subs.push(watcher);
}
notify() {
this.subs.forEach((watcher) => {
watcher.run();
});
}
}
Dep.targetWatcher = null;
function observer(data) {
Object.keys(data).forEach((key) => {
defineReactive(data, key);
});
function defineReactive(target, key) {
let dep = new Dep();
let val = target[key];
Object.defineProperty(target, key, {
get() {
console.log("getter");
if (Dep.targetWatcher) {
dep.addDep(Dep.targetWatcher);
}
return val;
},
set(newValue) {
console.log("setter");
val = newValue;
dep.notify();
},
});
}
}
let state = {
a: 1,
b: 2,
};
observer(state);
new Watcher(state, "a", () => {
console.log("a has change", state.a);
});
new Watcher(state, "b", () => {
console.log("b has change", state.b);
});
setTimeout(() => {
state.a = 2;
}, 1000);
setTimeout(() => {
state.a = 2;
}, 500);