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

useInViewport

SebelumnyaBerikutnya

Apakah sebuah elemen sedang terlihat di layar.

Terlihat: — · rasio —

Gulung ke bawah…
Kotak yang dipantau.

IntersectionObserver, bukan menghitung posisi saat scroll. Bedanya bukan gaya: menghitung posisi berarti bekerja di setiap peristiwa scroll, di utas utama, untuk setiap elemen yang dipantau. IntersectionObserver dikerjakan peramban di luar itu dan cuma memanggil balik saat keadaannya benar-benar berubah.

Ini yang dipakai untuk memuat gambar saat mendekat, menandai bagian aktif di daftar isi, dan memuat halaman berikutnya saat dasar daftar tersentuh.

Pemasangan ​

npx shadcn-vue@latest add @kliping/use-in-viewport

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 UseInViewportOptions {
  rootMargin?: string
  threshold?: number | number[]
  /** Elemen yang dianggap "layar". Kosongkan untuk viewport. */
  root?: TargetElemen
  callback?: (entri: IntersectionObserverEntry) => void
}

export function useInViewport(
  target: TargetElemen | TargetElemen[],
  options: UseInViewportOptions = {},
) {
  const { rootMargin, threshold, root, callback } = options

  const inViewport = ref<boolean | undefined>(undefined)
  const ratio = ref<number | undefined>(undefined)

  let pengamat: IntersectionObserver | undefined

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

  const berhentiPantau = watch(
    () => {
      const daftar = Array.isArray(target) ? target : [target]
      return daftar.map(t => bacaElemen(t))
    },
    (elemen) => {
      bongkar()

      const ada = elemen.filter(Boolean) as Element[]
      if (!ada.length || typeof IntersectionObserver === 'undefined')
        return

      pengamat = new IntersectionObserver(
        (daftar) => {
          for (const entri of daftar) {
            ratio.value = entri.intersectionRatio
            inViewport.value = entri.isIntersecting
            callback?.(entri)
          }
        },
        {
          rootMargin,
          threshold,
          root: bacaElemen(root) as Element | null ?? null,
        },
      )

      for (const el of ada)
        pengamat.observe(el)
    },
    { immediate: true, flush: 'post' },
  )

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

  if (getCurrentScope())
    onScopeDispose(berhenti)

  return { inViewport, ratio, stop: berhenti }
}

API ​

ts
export interface UseInViewportOptions {
  rootMargin?: string
  threshold?: number | number[]
  /** Elemen yang dianggap "layar". Kosongkan untuk viewport. */
  root?: TargetElemen
  callback?: (entri: IntersectionObserverEntry) => void
}

export function useInViewport(
  target: TargetElemen | TargetElemen[],
  options: UseInViewportOptions = {},
)
useHoveruseIsMatchMedia

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