diff --git a/packages/core/useCloned/index.ts b/packages/core/useCloned/index.ts index 7c95cacd01d..d40080181f0 100644 --- a/packages/core/useCloned/index.ts +++ b/packages/core/useCloned/index.ts @@ -29,7 +29,9 @@ export interface UseClonedReturn { sync: () => void } -function cloneFnJSON(source: T): T { +export type CloneFn = (x: F) => T + +export function cloneFnJSON(source: T): T { return JSON.parse(JSON.stringify(source)) } diff --git a/packages/core/useVModel/index.ts b/packages/core/useVModel/index.ts index 9e7cdb36245..2e7e3af4608 100644 --- a/packages/core/useVModel/index.ts +++ b/packages/core/useVModel/index.ts @@ -1,8 +1,8 @@ import { isDef, isFunction } from '@vueuse/shared' import type { UnwrapRef } from 'vue-demi' import { computed, getCurrentInstance, isVue2, ref, watch } from 'vue-demi' - -export type CloneFn = (x: F) => T +import type { CloneFn } from '../useCloned' +import { cloneFnJSON } from '../useCloned' export interface UseVModelOptions { /** @@ -32,16 +32,15 @@ export interface UseVModelOptions { */ defaultValue?: T /** - * Clone when getting the value from props, shortcut for: JSON.parse(JSON.stringify(value)). - * Default to false + * Clone the props. + * Accepts a custom clone function. + * When setting to `true`, it will use `JSON.parse(JSON.stringify(value))` to clone. * * @default false */ clone?: boolean | CloneFn } -const defaultCloneFn = (v: F): T => JSON.parse(JSON.stringify(v)) - /** * Shorthand for v-model binding, props + emit -> ref * @@ -83,21 +82,33 @@ export function useVModel

isDef(props[key!]) ? props[key!] : defaultValue - const cloneFn = (val: P[K]) => isFunction(clone) ? clone(val) : defaultCloneFn(val) + const cloneFn = (val: P[K]) => !clone + ? val + : isFunction(clone) + ? clone(val) + : cloneFnJSON(val) + + const getValue = () => isDef(props[key!]) + ? cloneFn(props[key!]) + : defaultValue if (passive) { const initialValue = getValue() - const proxy = ref(clone && initialValue ? cloneFn(initialValue) : initialValue!) + const proxy = ref(initialValue!) - watch(() => props[key!], v => proxy.value = v as UnwrapRef) + watch( + () => props[key!], + v => proxy.value = cloneFn(v) as UnwrapRef, + ) - watch(proxy, (v) => { - if (v !== props[key!] || deep) - _emit(event, v) - }, { - deep, - }) + watch( + proxy, + (v) => { + if (v !== props[key!] || deep) + _emit(event, v) + }, + { deep }, + ) return proxy }