Skip to content

Видимость элемента ​

useElementVisibility(target, options?) — реактивная видимость элемента на базе IntersectionObserver. SSR-safe: наблюдение начинается, как только target разрешается в реальный элемент на клиенте.

ts
function useElementVisibility(
  target: MaybeRefOrGetter<HTMLElement | null | undefined>,
  options?: UseElementVisibilityOptions,
): UseElementVisibilityReturn

Каждый вызов использует один общий модульный инстанс createVisibilityEngine() — согласуется с собственным дизайном движка на пулящихся обсерверах.

Опции ​

threshold ​

MaybeRefOrGetter<number | number[] | undefined> · по умолчанию: viewportDefaults.threshold (0, если не переопределено)

Изменение этого значения как ref/геттера вызывает настоящую переподписку — членство в пуле привязано к нему, так же как к rootMargin/root.

rootMargin ​

MaybeRefOrGetter<string | undefined> · по умолчанию: viewportDefaults.rootMargin ('0px', если не переопределено)

То же поведение переподписки, что у threshold.

root ​

MaybeRefOrGetter<HTMLElement | null | undefined> · по умолчанию: null

То же поведение переподписки, что у threshold/rootMargin.

once ​

MaybeRefOrGetter<boolean | undefined> · по умолчанию: viewportDefaults.once (false, если не переопределено)

В отличие от threshold/rootMargin/root, изменение этого значения обновляет уже существующую подписку вживую — без переподписки, без пересоздания observer'а.

onEnter ​

(info: IntersectionInfo) => void · по умолчанию: —

onLeave ​

(info: IntersectionInfo) => void · по умолчанию: —

onEnter/onLeave осознанно остаются обычными значениями, не MaybeRefOrGetter — колбэк, замыкающий .value рефа, и так читает его заново при каждом вызове, поскольку composables в Vue выполняются один раз в setup(). Здесь просто нечего чинить обёрткой.

threshold/rootMargin/once берут значение по умолчанию из общего объекта viewportDefaults, а не из жёстко заданных 0/'0px'/false — см. setViewportDefaults() ниже и Модуль Nuxt — там описано, как это обычно настраивается на уровне приложения.

Возвращаемое значение ​

isVisible ​

Ref<boolean>

ratio ​

Ref<number>

Текущий intersectionRatio элемента.

Пример:

vue
<script setup lang="ts">
import { ref } from 'vue'
import { useElementVisibility } from '@macrulez/inview-vue'

const card = ref<HTMLElement | null>(null)
const { isVisible } = useElementVisibility(card, { threshold: 0.5, once: true })
</script>

<template>
  <div ref="card" :class="{ 'is-visible': isVisible }">...</div>
</template>

Автоматически переподписывается при изменении target, threshold, rootMargin или root; once вместо этого обновляет уже существующую подписку вживую.

threshold/rootMargin/root/once принимают ref/геттер, а не только обычное значение:

vue
<script setup lang="ts">
const stopOnceUserOptsIn = ref(false)
const { isVisible } = useElementVisibility(card, { once: stopOnceUserOptsIn })
// позже: stopOnceUserOptsIn.value = true — обновляется вживую, без переподписки
</script>

Глобальные значения по умолчанию ​

setViewportDefaults() / viewportDefaults — общие для всего пакета значения по умолчанию для threshold/rootMargin/once, переопределяемые один раз на уровне приложения вместо передачи одних и тех же опций в каждое место вызова. Читаются и этим composable, и v-reveal, и <InView>.

ts
interface ViewportDefaults {
  threshold: number | number[]
  rootMargin: string
  once: boolean
}

const viewportDefaults: ViewportDefaults // { threshold: 0, rootMargin: '0px', once: false }

function setViewportDefaults(overrides: Partial<ViewportDefaults>): void

setViewportDefaults() перезаписывает только те поля, что вы реально передали — она подмешивает их в общий объект viewportDefaults, а не заменяет его целиком. Именно это под капотом вызывает @macrulez/inview-nuxt из своих опций модуля.