You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
vue3/docs/学习vue3/watchEffect实现原理.js

63 lines
1.7 KiB

function isObject(obj) {
return obj !== null && typeof obj === 'object';
}
function reactive(target) {
if (!isObject(target)) return target;
const handler = {
get(target, key, receiver) {
track(target, key);
const result = Reflect.get(target, key, receiver);
return isObject(result) ? reactive(result) : result;
},
set(target, key, value, receiver) {
const oldValue = target[key];
if (oldValue !== value) {
const result = Reflect.set(target, key, value, receiver);
trigger(target, key);
return result;
}
}
};
return new Proxy(target, handler);
}
const targetMap = new WeakMap();
const effectStack = [];
function track(target, key) {
if (effectStack.length) {
let depsMap = targetMap.get(target);
if (!depsMap) targetMap.set(target, (depsMap = new Map()));
let dep = depsMap.get(key);
if (!dep) depsMap.set(key, (dep = new Set()));
dep.add(effectStack[effectStack.length - 1]);
}
}
function trigger(target, key) {
const depsMap = targetMap.get(target);
if (depsMap) {
const effects = new Set([...(depsMap.get(key) || [])]);
effects.forEach(effect => effect());
}
}
function watchEffect(effect) {
effectStack.push(effect);
try {
return effect();
} finally {
effectStack.pop();
}
}
// 使用示例
const data = reactive({ count: 0 });
watchEffect(() => {
console.log(`Count is: ${data.count}`);
});
setTimeout(() => {
data.count++; // 触发副作用,在控制台打印出新的count值
}, 1000);