alioth/before/cha/14=vue3/docs/学习vue3/watchEffect实现原理.js
2025-05-30 09:18:01 +08:00

64 lines
1.7 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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);