Skip to content

Headless-загрузка изображений

useImage() — headless composable. Используйте, когда нужен конечный автомат состояния загрузки и вычисляемые атрибуты, но требуется своя разметка.

ts
const {
  status, // Ref<'idle' | 'loading' | 'loaded' | 'error'>
  isLoaded, // ComputedRef<boolean>
  isError, // ComputedRef<boolean>
  imgAttrs, // ComputedRef<ImgAttrs> — готов для spread на <img>
  observe, // (el: Ref<HTMLElement | null>) => void
  onImgLoad, // () => void — вызывать из img @load
  onImgError, // () => void — вызывать из img @error
} = useImage(options)

Опции

src

string | SrcSet, опционален. URL изображения или объект формата.

widths

number[] · по умолчанию: []. Ширины для генерации srcset на основе ширины (w).

densities

number[] | Record<number, string>, опционален. Дескрипторы плотности (1x/2x/3x); список переиспользует src, объект даёт отдельные файлы; имеет приоритет над widths, игнорирует sizes.

sizes

string, опционален. Значение атрибута sizes (только для srcset на основе ширины).

lazy

boolean · по умолчанию: true. Включить IntersectionObserver.

rootMargin

string · по умолчанию: "200px". rootMargin для IO.

threshold

number · по умолчанию: 0. threshold для IO.

fit

ObjectFit · по умолчанию: "cover". Стиль object-fit.

maxRetries

number · по умолчанию: 0. Максимум попыток повтора при неудаче загрузки.

retryDelay

number · по умолчанию: 1000. Начальная задержка в мс; удваивается на каждом повторе.

Конечный автомат

idle  →  loading  →  loaded
                  →  error
  • При lazy: true — переход в loading, когда наблюдаемый элемент попадает во вьюпорт (внутри использует useLazyLoad())
  • При lazy: false — переход в loading сразу после onMounted

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

status

Ref<ImageStatus>. Текущее состояние загрузки.

isLoaded

ComputedRef<boolean>. true, когда status === 'loaded'.

isError

ComputedRef<boolean>. true, когда status === 'error'.

imgAttrs

ComputedRef<object>. { src, srcset?, sizes?, style } — готов для v-bind.

observe

Function. Передайте Ref<HTMLElement>, чтобы начать отслеживание пересечения.

onImgLoad

Function. Вызывайте из <img @load> для перехода в loaded.

onImgError

Function. Вызывайте из <img @error> для перехода в error.

Пример — кастомный рендер

vue
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { useImage } from '@macrulez/vue-image-kit'

const containerRef = ref<HTMLElement | null>(null)

const { status, isLoaded, imgAttrs, observe, onImgLoad, onImgError } = useImage({
  src: '/photo.jpg',
  widths: [400, 800, 1200],
  sizes: '(max-width: 768px) 100vw, 50vw',
})

onMounted(() => {
  observe(containerRef)
})
</script>

<template>
  <div ref="containerRef" class="image-wrapper">
    <div v-if="status === 'idle'" class="skeleton" />

    <img
      v-if="status === 'loading' || isLoaded"
      v-bind="imgAttrs"
      alt="Photo"
      :class="{ visible: isLoaded }"
      @load="onImgLoad"
      @error="onImgError"
    />

    <div v-if="status === 'error'" class="error-state">Failed to load</div>
  </div>
</template>

<style scoped>
img {
  opacity: 0;
  transition: opacity 0.3s;
}
img.visible {
  opacity: 1;
}
</style>