97 lines
2.0 KiB
JavaScript
97 lines
2.0 KiB
JavaScript
const targetMap = new WeakMap(); // 用原始对象作为key,依赖映射作为value
|
||
let activeEffect = null; // 保存当前的需要订阅通知的effect
|
||
|
||
function track(target, key) {
|
||
if (activeEffect) {
|
||
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(activeEffect); // 将efect添加进通知set
|
||
}
|
||
}
|
||
|
||
function trigger(target, key) {
|
||
const depsMap = targetMap.get(target);
|
||
if (!depsMap) return;
|
||
const deps = depsMap.get(key);
|
||
deps.forEach((effect) => {
|
||
effect();
|
||
});
|
||
}
|
||
|
||
export function reactive(target) {
|
||
const hander = {
|
||
get(target, key, receiver) {
|
||
const result = Reflect.get(target, key, receiver);
|
||
track(target, key);
|
||
return result;
|
||
},
|
||
|
||
set(target, key, value, receiver) {
|
||
let oldValue = target[key];
|
||
let result = Reflect.set(target, key, value, receiver);
|
||
if (oldValue !== value) {
|
||
trigger(target, key);
|
||
}
|
||
return result;
|
||
},
|
||
};
|
||
|
||
return new Proxy(target, hander);
|
||
}
|
||
|
||
// 创建ref,为基本数据类型赋予响应式功能
|
||
export function ref(raw) {
|
||
const r = {
|
||
get value() {
|
||
track(r, "value");
|
||
return raw;
|
||
},
|
||
|
||
set value(newVal) {
|
||
raw = newVal;
|
||
trigger(r, "value");
|
||
},
|
||
};
|
||
|
||
return r;
|
||
}
|
||
|
||
// 绑定副作用
|
||
export function effect(effect) {
|
||
activeEffect = effect;
|
||
activeEffect();
|
||
activeEffect = null;
|
||
}
|
||
|
||
// 计算属性
|
||
export function computed(getter) {
|
||
let result = ref();
|
||
effect(() => (result.value = getter()));
|
||
return result;
|
||
}
|
||
|
||
// watch
|
||
export function watch(source, callback) {
|
||
let getter;
|
||
if (typeof source === "function") {
|
||
getter = source;
|
||
} else {
|
||
getter = () => source.value;
|
||
}
|
||
|
||
let oldValue, newValue;
|
||
const effectFn = () => {
|
||
newValue = getter();
|
||
if (oldValue !== undefined) callback(newValue, oldValue); // watch第一次不需要执行
|
||
oldValue = newValue;
|
||
};
|
||
|
||
effect(effectFn);
|
||
}
|