/
index.ts
77 lines (64 loc) · 1.83 KB
/
index.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
74
75
76
77
import type { ComputedGetter, ComputedRef, WatchSource, WritableComputedOptions, WritableComputedRef } from 'vue-demi'
import { customRef, ref, watch } from 'vue-demi'
import type { Fn } from '../utils'
import { isFunction } from '../utils'
export interface ComputedWithControlRefExtra {
/**
* Force update the computed value.
*/
trigger(): void
}
export interface ComputedRefWithControl<T> extends ComputedRef<T>, ComputedWithControlRefExtra {}
export interface WritableComputedRefWithControl<T> extends WritableComputedRef<T>, ComputedWithControlRefExtra {}
export function computedWithControl<T, S>(
source: WatchSource<S> | WatchSource<S>[],
fn: ComputedGetter<T>
): ComputedRefWithControl<T>
export function computedWithControl<T, S>(
source: WatchSource<S> | WatchSource<S>[],
fn: WritableComputedOptions<T>
): WritableComputedRefWithControl<T>
/**
* Explicitly define the deps of computed.
*
* @param source
* @param fn
*/
export function computedWithControl<T, S>(
source: WatchSource<S> | WatchSource<S>[],
fn: ComputedGetter<T> | WritableComputedOptions<T>,
) {
let v: T = undefined!
let track: Fn
let trigger: Fn
const dirty = ref(true)
const update = () => {
dirty.value = true
trigger()
}
watch(source, update, { flush: 'sync' })
const get = isFunction(fn) ? fn : fn.get
const set = isFunction(fn) ? undefined : fn.set
const result = customRef<T>((_track, _trigger) => {
track = _track
trigger = _trigger
return {
get() {
if (dirty.value) {
v = get()
dirty.value = false
}
track()
return v
},
set(v) {
set?.(v)
},
}
}) as ComputedRefWithControl<T>
if (Object.isExtensible(result))
result.trigger = update
return result
}
// alias
export { computedWithControl as controlledComputed }