forked from vueuse/vueuse
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
100 lines (90 loc) · 2.34 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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import { isDef } from '@vueuse/shared'
import type { UnwrapRef } from 'vue-demi'
import { computed, getCurrentInstance, isVue2, ref, watch } from 'vue-demi'
export interface VModelOptions<T> {
/**
* When passive is set to `true`, it will use `watch` to sync with props and ref.
* Instead of relying on the `v-model` or `.sync` to work.
*
* @default false
*/
passive?: boolean
/**
* When eventName is set, it's value will be used to overwrite the emit event name.
*
* @default undefined
*/
eventName?: string
/**
* Attempting to check for changes of properties in a deeply nested object or array.
* Apply only when `passive` option is set to `true`
*
* @default false
*/
deep?: boolean
/**
* Defining default value for return ref when no value is passed.
*
* @default undefined
*/
defaultValue?: T
}
/**
* Shorthand for v-model binding, props + emit -> ref
*
* @see https://vueuse.org/useVModel
* @param props
* @param key (default 'value' in Vue 2 and 'modelValue' in Vue 3)
* @param emit
*/
export function useVModel<P extends object, K extends keyof P, Name extends string>(
props: P,
key?: K,
emit?: (name: Name, ...args: any[]) => void,
options: VModelOptions<P[K]> = {},
) {
const {
passive = false,
eventName,
deep = false,
defaultValue,
} = options
const vm = getCurrentInstance()
// @ts-expect-error mis-alignment with @vue/composition-api
const _emit = emit || vm?.emit || vm?.$emit?.bind(vm) || vm?.proxy?.emit
let event: string | undefined = eventName
if (!key) {
if (isVue2) {
const modelOptions = vm?.proxy?.$options?.model
key = modelOptions?.value || 'value' as K
if (!eventName)
event = modelOptions?.event || 'input'
}
else {
key = 'modelValue' as K
}
}
event = eventName || event || `update:${key!.toString()}`
const getValue = () => isDef(props[key!]) ? props[key!] : defaultValue
if (passive) {
const proxy = ref<P[K]>(getValue()!)
watch(() => props[key!], v => proxy.value = v as UnwrapRef<P[K]>)
watch(proxy, (v) => {
if (v !== props[key!] || deep)
_emit(event, v)
}, {
deep,
})
return proxy
}
else {
return computed<P[K]>({
get() {
return getValue()!
},
set(value) {
_emit(event, value)
},
})
}
}