1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
| const observeWeakMap = new WeakMap(); let activeEffect = null;
export const effect = (eff) => { activeEffect = eff; activeEffect(); activeEffect = null; };
const track = (target, key) => { if (activeEffect) { let depsMap = observeWeakMap.get(target); if (!depsMap) { depsMap = new Map(); observeWeakMap.set(target, depsMap); } let depsSet = depsMap.get(key); if (!depsSet) { depsSet = new Set(); depsMap.set(key, depsSet); } depsSet.add(activeEffect); } };
const trigger = (target, key) => { const depsMap = observeWeakMap.get(target); if (!depsMap) return; const depsSet = depsMap.get(key); if (!depsSet) return; depsSet.forEach((eff) => { eff(); }); };
export const reactive = (target) => { const handler = { get(target, key, receiver) { const result = Reflect.get(target, key, receiver); track(target, key); return result; }, set(target, key, value, receiver) { const oldValue = Reflect.get(target, key, receiver); const result = Reflect.set(target, key, value, receiver); if (oldValue !== value) { trigger(target, key); } return result; }, }; return new Proxy(target, handler); }; export const ref = (value) => { const target = { _value: value }; const key = "value"; const _key = "_value"; Object.defineProperty(target, key, { get() { const result = Reflect.get(target, _key); track(target, key); return result; }, set(value) { const oldValue = Reflect.get(target, _key); Reflect.set(target, _key, value); if (oldValue !== value) { trigger(target, key); } }, }); return target; }; export const computed = (getter) => { const r = { _dirty: true, _init: false, get value() { if (this._dirty) { if (!this._init) { activeEffect = () => { if (!this._dirty) this._dirty = true; }; } this._value = getter(); if (!this._init) { activeEffect = null; this._init = true; } this._dirty = false; } return this._value; }, }; return r; };
|