kliping.pro
  • Docs
  • Directory
  • Colors
  • Typeset
Hooks
  • State7
    • useBoolean
    • useControllableValue
    • useCounter
    • useDebounce
    • useResetState
    • useThrottle
    • useToggle
  • Advanced6
  • Lifecycle16
  • Browser21
  • Development1
  • Third-Party4
  • Libraries4

useControllableValue

PreviousNext

Satu nilai yang bisa dikendalikan dari luar, atau mengurus dirinya sendiri.

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.

Installation ​

pnpm dlx 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> {
  /** Used when neither the value prop nor the default-value prop is passed. */
  defaultValue?: T
  /** Name of the default-value prop. Default: `defaultValue`. */
  defaultValuePropName?: string
  /** Name of the controlled-value prop. Default: `value`. */
  valuePropName?: string
  /** Name of the change-notification prop. Default: `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 readProps = () => toValue(props) ?? {}

  const isControlled = computed(() => readProps()[valuePropName] !== undefined)

  const initialValue = (): T => {
    const p = readProps()
    if (p[valuePropName] !== undefined) return p[valuePropName]
    if (p[defaultValuePropName] !== undefined) return p[defaultValuePropName]
    return defaultValue as T
  }

  const inner = ref(initialValue()) as { value: T }

  const state = computed<T>(() => (isControlled.value ? readProps()[valuePropName] : inner.value))

  const setState = (value: T | ((current: T) => T), ...rest: any[]) => {
    const next = typeof value === 'function' ? (value as (current: T) => T)(state.value) : value

    if (!isControlled.value) inner.value = next

    readProps()[trigger]?.(next, ...rest)
  }

  return { state, setState }
}

API ​

ts
export interface UseControllableValueOptions<T> {
  /** Used when neither the value prop nor the default-value prop is passed. */
  defaultValue?: T
  /** Name of the default-value prop. Default: `defaultValue`. */
  defaultValuePropName?: string
  /** Name of the controlled-value prop. Default: `value`. */
  valuePropName?: string
  /** Name of the change-notification prop. Default: `onChange`. */
  trigger?: string
}

export function useControllableValue<T = any>(
  props: MaybeRefOrGetter<Record<string, any>>,
  options: UseControllableValueOptions<T> = {},
)
PrevioususeBooleanNext useCounter

On This Page

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