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

useElementSize

SebelumnyaBerikutnya

Ukuran sebuah elemen, diikuti lewat ResizeObserver.

0 × 0 px

Ukuran sebuah elemen, diikuti lewat ResizeObserver.

Dua hal yang dibawa dari sumbernya karena keduanya jawaban atas masalah nyata, bukan kerumitan yang bisa dibuang:

  1. SVG diukur lewat getBoundingClientRect. contentBoxSize untuk elemen SVG dilaporkan berbeda-beda antar peramban, dan sebagiannya nol.
  2. observe dengan opsi box dibungkus try/catch. Peramban lama melempar untuk nilai box yang tidak dikenalnya; pengamatan tanpa opsi tetap lebih baik daripada tidak mengamati sama sekali.

Pemasangan ​

npx shadcn-vue@latest add @kliping/use-element-size

Perlu @kliping terdaftar di components.json project Anda. Lihat cara menyiapkannya.

Ikut terpasang sendiri: target.

Salin dulu target — masing-masing memuat sumbernya di halamannya sendiri — lalu tempel berkas ini.

ts
import { getCurrentScope, onScopeDispose, ref, watch } from 'vue'
import { bacaElemen } from '@/lib/target'
import type { TargetElemen } from '@/lib/target'

export interface UkuranElemen {
  width: number
  height: number
}

export interface UseElementSizeOptions {
  /** Kotak yang diukur. Bawaan: `content-box`. */
  box?: ResizeObserverBoxOptions
}

function ukuranDariEntri(
  entri: ResizeObserverEntry,
  box: ResizeObserverBoxOptions,
): UkuranElemen {
  const kotak = box === 'border-box'
    ? entri.borderBoxSize
    : box === 'device-pixel-content-box'
      ? entri.devicePixelContentBoxSize
      : entri.contentBoxSize

  const daftar = kotak
    ? (Array.isArray(kotak) ? kotak : [kotak]) as readonly ResizeObserverSize[]
    : []

  if (daftar.length) {
    return {
      width: daftar.reduce((n, u) => n + u.inlineSize, 0),
      height: daftar.reduce((n, u) => n + u.blockSize, 0),
    }
  }

  return { width: entri.contentRect.width, height: entri.contentRect.height }
}

export function useElementSize(
  target: TargetElemen,
  initialSize: UkuranElemen = { width: 0, height: 0 },
  options: UseElementSizeOptions = {},
) {
  const { box = 'content-box' } = options

  const width = ref(initialSize.width)
  const height = ref(initialSize.height)

  let pengamat: ResizeObserver | undefined

  const bongkar = () => {
    pengamat?.disconnect()
    pengamat = undefined
  }

  const setel = (ukuran: UkuranElemen) => {
    width.value = ukuran.width
    height.value = ukuran.height
  }

  const berhentiPantau = watch(
    () => bacaElemen(target),
    (elemen) => {
      bongkar()

      if (!elemen || !('getBoundingClientRect' in elemen)) {
        setel({ width: 0, height: 0 })
        return
      }

      const el = elemen as Element

      if (typeof ResizeObserver === 'undefined') {
        const kotak = el.getBoundingClientRect()
        setel({ width: kotak.width, height: kotak.height })
        return
      }

      const svg = typeof SVGElement !== 'undefined' && el instanceof SVGElement

      pengamat = new ResizeObserver((daftar) => {
        const entri = daftar[0]
        if (!entri)
          return

        if (svg) {
          const kotak = el.getBoundingClientRect()
          setel({ width: kotak.width, height: kotak.height })
          return
        }

        setel(ukuranDariEntri(entri, box))
      })

      try {
        pengamat.observe(el, { box })
      }
      catch {
        pengamat.observe(el)
      }
    },
    { immediate: true, flush: 'post' },
  )

  const berhenti = () => {
    bongkar()
    berhentiPantau()
  }

  if (getCurrentScope())
    onScopeDispose(berhenti)

  return { width, height, stop: berhenti }
}

API ​

ts
export interface UkuranElemen {
  width: number
  height: number
}

export interface UseElementSizeOptions {
  /** Kotak yang diukur. Bawaan: `content-box`. */
  box?: ResizeObserverBoxOptions
}

export function useElementSize(
  target: TargetElemen,
  initialSize: UkuranElemen = { width: 0, height: 0 },
  options: UseElementSizeOptions = {},
)
useDocumentVisibilityuseEventListener

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