Vue2 响应式源码实现
function reactive(obj) {
Object.keys(obj).forEach((key) => {
let value = obj[key];
Object.defineProperty(obj, key, {
get() {
const depend = getDepend(obj, key);
depend.addDepend();
return value;
},
set(newVal) {
value = newVal;
const depend = getDepend(obj, key);
depend.notify();
},
});
});
return obj;
}
let curDepsFunc = null;
class Deps {
constructor() {
this.dep = new Set();
}
addDepend() {
if (curDepsFunc) {
this.dep.add(curDepsFunc);
}
}
notify() {
for (const fn of this.dep) {
fn();
}
}
}
const dependWeakMap = new WeakMap();
function getDepend(target, key) {
let depsMap = dependWeakMap.get(target);
if (!depsMap) {
depsMap = new Map();
dependWeakMap.set(target, depsMap);
}
let deps = depsMap.get(key);
if (!deps) {
deps = new Deps();
depsMap.set(key, deps);
}
return deps;
}
function watchEffect(fn) {
curDepsFunc = fn;
fn();
}
const proxyObj = reactive({
name: 'Kobe',
age: 18,
});
watchEffect(function () {
console.log(proxyObj.name);
console.log(proxyObj.age);
});
// watchEffect(function () {
// console.log(proxyObj.age);
// });
proxyObj.name = 'wangweiping';
proxyObj.name = 'xieting';
proxyObj.age = 2012;