import {Meta} from '@storybook/addon-docs/blocks'

<Meta title='@dxtmisha/ru/functional/# Ленивая загрузка элементов'/>

# Отслеживание видимости элементов (Ленивая загрузка)

Это семейство хуков предоставляет производительную обертку над нативным браузерным API `IntersectionObserver`. Они используются для отслеживания появления DOM-элементов в зоне видимости экрана (или с заданным отступом). 

Главные сценарии применения:
- **Ленивая загрузка изображений**: загружать картинки только тогда, когда пользователь почти доскроллил до них.
- **Бесконечная лента (Infinite Scroll)**: подгружать новые данные при приближении к концу списка.
- **Анимации при прокрутке**: запускать эффекты только тогда, когда блок реально виден глазам пользователя.

## Особенности и какой хук выбрать?

- **`useLazyItemByMarginRef` (Рекомендуемый)**: "Умный" синглтон-хук. Он **переиспользует** один и тот же `IntersectionObserver` для всех элементов, у которых совпадает настройка `rootMargin`. Это кардинально экономит потребление памяти и CPU. Если у вас список из 1000 ленивых картинок, будет создан только 1 обсервер, а не 1000.
- **`useLazyRef` (Для сложных задач)**: Низкоуровневый базовый хук. Создает строго **индивидуальный** `IntersectionObserver` для конкретной задачи. Полезен, когда вам нужны специфические настройки (например, сложный массив `threshold`, кастомный `root` элемент) или полный ручной контроль над жизнью обсервера через метод `disconnect`.

## Примеры использования

### 1. Массовое отслеживание (`useLazyItemByMarginRef`)

Самый частый способ работы. Указываете элемент и желаемый отступ (на каком расстоянии до экрана сработает триггер). Возвращает реактивный флаг видимости.

```vue
<script setup lang="ts">
import { ref } from 'vue'
import { useLazyItemByMarginRef } from '@dxtmisha/functional'

const imageRef = ref<HTMLElement>()

// Параметр '128px' означает, что статус станет true, 
// когда до элемента останется 128px скролла.
const { lazyItemStatus } = useLazyItemByMarginRef(imageRef, '128px')
</script>

<template>
  <!-- Рендерим тяжелый контент только если мы к нему приблизились -->
  <img 
    ref="imageRef" 
    :src="lazyItemStatus ? 'heavy-image.jpg' : 'placeholder.jpg'" 
  />
</template>
```

### 2. Индивидуальный обсервер (`useLazyRef`)

Используется для точечных задач со специфическими настройками API `IntersectionObserver`.

```typescript
import { ref } from 'vue'
import { useLazyRef } from '@dxtmisha/functional'

const myContainer = ref<HTMLElement>()

// 1. Создаем уникальный обсервер
const observer = useLazyRef({
  root: document.getElementById('scrollable-area'),
  rootMargin: '0px',
  threshold: [0, 0.5, 1.0] // Отслеживаем каждые 50% видимости
})

// 2. Добавляем элемент для слежения
const isVisible = observer.addLazyItem(myContainer)

// 3. Вы можете получить сырые данные IntersectionObserverEntry:
// observer.getItem(myContainer.value)

// 4. Ручная очистка при необходимости:
// observer.removeLazyItem(myContainer.value)
// observer.disconnectLazy()
```
