useControllableValue
Satu nilai yang bisa dikendalikan dari luar, atau mengurus dirinya sendiri.
Keadaan: sembunyi
onChange terakhir: —
Untuk v-model biasa, jangan pakai ini — defineModel() bawaan Vue 3.4+ sudah menyelesaikannya dengan lebih sedikit kode. Composable ini untuk pola yang tidak tercakup defineModel: pasangan prop seperti open / defaultOpen / onUpdate:open, yaitu komponen yang harus bekerja baik saat induknya ikut mengatur maupun saat dibiarkan sendiri.
Penanda "terkendali" di sini adalah !== undefined, bukan memeriksa ada tidaknya kunci. Objek props Vue selalu memuat semua kunci yang dideklarasikan, dan yang tidak dikirim bernilai undefined — memeriksa keberadaan kuncinya akan membuat setiap komponen dikira terkendali, dan tidak ada satu pun yang bisa mengurus nilainya sendiri.
Penandanya reaktif, jadi komponen yang berpindah dari tak terkendali jadi terkendali di tengah jalan ikut terlayani.
Pemasangan
npx shadcn-vue@latest add @kliping/use-controllable-value Perlu @kliping terdaftar di components.json project Anda. Lihat cara menyiapkannya.
Tanpa dependensi — tidak ada berkas lain yang ikut terpasang.
Salin kode berikut ke project Anda.
import { computed, ref, toValue } from 'vue'
import type { MaybeRefOrGetter } from 'vue'
export interface UseControllableValueOptions<T> {
/** Dipakai kalau prop nilai maupun prop nilai-awal sama-sama tidak dikirim. */
defaultValue?: T
/** Nama prop nilai awal. Bawaan: `defaultValue`. */
defaultValuePropName?: string
/** Nama prop nilai terkendali. Bawaan: `value`. */
valuePropName?: string
/** Nama prop pemberi kabar perubahan. Bawaan: `onChange`. */
trigger?: string
}
export function useControllableValue<T = any>(
props: MaybeRefOrGetter<Record<string, any>>,
options: UseControllableValueOptions<T> = {},
) {
const {
defaultValue,
defaultValuePropName = 'defaultValue',
valuePropName = 'value',
trigger = 'onChange',
} = options
const baca = () => toValue(props) ?? {}
const terkendali = computed(() => baca()[valuePropName] !== undefined)
const nilaiAwal = (): T => {
const p = baca()
if (p[valuePropName] !== undefined)
return p[valuePropName]
if (p[defaultValuePropName] !== undefined)
return p[defaultValuePropName]
return defaultValue as T
}
const dalam = ref(nilaiAwal()) as { value: T }
const state = computed<T>(() =>
terkendali.value ? baca()[valuePropName] : dalam.value,
)
const setState = (nilai: T | ((kini: T) => T), ...sisa: any[]) => {
const hasil = typeof nilai === 'function'
? (nilai as (kini: T) => T)(state.value)
: nilai
// Saat terkendali, yang berhak mengubah nilainya adalah induknya. Yang
// dilakukan di sini cuma memberi kabar; menulis ke state sendiri akan
// membuat tampilannya menyimpang dari sumber kebenarannya.
if (!terkendali.value)
dalam.value = hasil
baca()[trigger]?.(hasil, ...sisa)
}
return { state, setState }
}API
export interface UseControllableValueOptions<T> {
/** Dipakai kalau prop nilai maupun prop nilai-awal sama-sama tidak dikirim. */
defaultValue?: T
/** Nama prop nilai awal. Bawaan: `defaultValue`. */
defaultValuePropName?: string
/** Nama prop nilai terkendali. Bawaan: `value`. */
valuePropName?: string
/** Nama prop pemberi kabar perubahan. Bawaan: `onChange`. */
trigger?: string
}
export function useControllableValue<T = any>(
props: MaybeRefOrGetter<Record<string, any>>,
options: UseControllableValueOptions<T> = {},
)