-
Notifications
You must be signed in to change notification settings - Fork 0
/
reactive.ts
73 lines (62 loc) · 1.67 KB
/
reactive.ts
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
import { scope, register } from "./utils/magic-context";
import { useSubscription } from "./composables/use-subscription";
export interface Reactive<T> {
subscribe: (handler: (v: T) => void) => (() => void),
value: T;
}
function watchFn<T>(fn: () => T, dispatch: (v: T, isFirst: boolean) => void) {
let unsubscribeAll = () => {};
function compute(isFirst: boolean) {
const { onChange, value } = scope(fn);
dispatch(value, isFirst);
unsubscribeAll = onChange(compute);
}
compute(true);
return () => unsubscribeAll();
}
export function watch<T>(reactive: Reactive<T>, handler: (v: T) => void, options?: { immediate: boolean }) {
const unsubscribe = reactive.subscribe(handler);
if (options?.immediate) {
handler(reactive.value);
}
return unsubscribe;
}
export function ref<T>(value: T): Reactive<T> {
const { subscribe, dispatch } = useSubscription();
return {
subscribe,
get value() {
register(subscribe);
return value;
},
set value(v) {
value = v;
dispatch(value);
}
};
}
export function computed<T>(compute: () => T): Reactive<T> {
const { subscribe, onFirstSubscription, onLastUnsubscription, dispatch } = useSubscription();
let computedValue: any;
let unsubscribe: Function;
onFirstSubscription(() => {
unsubscribe = watchFn(compute, (value, isFirst) => {
computedValue = value;
if (!isFirst) dispatch(value);
});
});
onLastUnsubscription(() => {
unsubscribe();
});
function getComputedValue() {
subscribe(() => {})();
return computedValue;
}
return {
subscribe,
get value() {
register(subscribe);
return getComputedValue();
},
};
}