Kliping
KlipingBerandaDokumentasiKomponenBlocksVariasiTemplateDice UIHooks
Memulai
  • Pengenalan
  • Instalasi
  • Kredit
State
  • useBoolean
  • useControllableValue
  • useCounter
  • useDebounce
  • useResetState
  • useThrottle
  • useToggle
Lanjutan
  • useCreation
  • useCustomCompareEffect
  • useLatest
  • useLockFn
  • useMemoizedFn
  • usePrevious
Siklus Hidup
  • useDebounceEffect
  • useDebounceFn
  • useDeepCompareEffect
  • useDeepCompareLayoutEffect
  • useEffectEvent
  • useEffectWithTarget
  • useInterval
  • useIsHydrated
  • useIsomorphicLayoutEffect
  • useMount
  • useThrottleEffect
  • useThrottleFn
  • useTimeout
  • useUnmount
  • useUpdate
  • useUpdateEffect
Peramban
  • useActiveElement
  • useBattery
  • useClickAnyWhere
  • useClickAway
  • useClipboard
  • useDocumentVisibility
  • useElementSize
  • useEventListener
  • useFps
  • useFullscreen
  • useHash
  • useHover
  • useInViewport
  • useIsMatchMedia
  • useIsOnline
  • useMouse
  • useNetwork
  • useOs
  • useScrollLock
  • useTextSelection
  • useTitle
Pengembangan
  • useWhyDidYouUpdate
Paket Luar
  • useMcp
  • useQuery
  • useStickToBottom
  • useSwr
Pustaka
  • isBrowser
  • createContext
  • bacaElemen
  • saatTerpasang

useControllableValue

SebelumnyaBerikutnya

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.

ts
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 ​

ts
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> = {},
)
useBooleanuseCounter

Di halaman ini

PemasanganAPI
Dirilis di bawah lisensi MIT. Ditulis ulang untuk Vue dari shadcn-vue, shadcn-ui-blocks, dan shadcn-hooks. Hak cipta © 2026 Kliping