v-intersection-observer наблюдение за видимостью

v-intersection-observer — это директива Quasar для отслеживания появления и исчезновения элементов в зоне видимости пользователя. Она является оберткой над стандартным API Intersection Observer, предоставляя удобный синтаксис для реактивного взаимодействия с элементами DOM в рамках Vue.js.

Директива применяется к любому элементу следующим образом:

<template>
  <div v-intersection-observer="onVisibilityChange">
    Контент для наблюдения
  </div>
</template>

<script>
export default {
  methods: {
    onVisibilityChange({ entry, observer }) {
      console.log('Элемент видим:', entry.isIntersecting);
    }
  }
}
</script>

Ключевой момент: обработчик получает объект с entry и observer, где entry — это объект IntersectionObserverEntry, содержащий информацию о видимости элемента, а observer — сам наблюдатель.


Опции директивы

v-intersection-observer поддерживает объект конфигурации, позволяющий управлять поведением наблюдателя:

<div v-intersection-observer="{
  handler: onVisibilityChange,
  options: {
    root: null,
    rootMargin: '0px',
    threshold: 0.5
  },
  once: true
}">
  Контент с кастомными настройками
</div>

Пояснение ключевых свойств:

  • handler — функция, вызываемая при пересечении.

  • options — стандартные опции Intersection Observer:

    • root — элемент, относительно которого происходит отслеживание (по умолчанию null, что означает viewport).
    • rootMargin — отступы вокруг root, которые увеличивают или уменьшают область видимости.
    • threshold — число или массив чисел от 0 до 1, определяющее процент видимости элемента, при котором срабатывает обработчик.
  • once — если true, обработчик вызывается только один раз при первом пересечении.


Практические сценарии использования

  1. Ленивая загрузка изображений
<img v-intersection-observer="{
  handler: loadImage,
  options: { threshold: 0.1 },
  once: true
}" :data-src="imageSrc" alt="Lazy Image">

<script>
export default {
  methods: {
    loadImage({ entry }) {
      const img = entry.target;
      img.src = img.dataset.src;
    }
  }
}
</script>

Элемент начинает загружать изображение только тогда, когда появляется на экране.

  1. Анимации появления элементов
<div v-intersection-observer="animateOnView" class="fade-in">
  Текст для анимации
</div>

<script>
export default {
  methods: {
    animateOnView({ entry }) {
      if (entry.isIntersecting) {
        entry.target.classList.add('visible');
      }
    }
  }
}
</script>

<style>
.fade-in {
  opacity: 0;
  transition: opacity 0.6s ease-in-out;
}
.fade-in.visible {
  opacity: 1;
}
</style>

Эффект плавного появления активируется только при попадании элемента в область видимости.

  1. Отслеживание скролла для статистики

Можно фиксировать, какие секции страницы пользователь просмотрел:

<section v-for="section in sections" :key="section.id"
         v-intersection-observer="recordView">
  {{ section.title }}
</section>

<script>
export default {
  data() {
    return { viewedSections: new Set() }
  },
  methods: {
    recordView({ entry }) {
      if (entry.isIntersecting) {
        this.viewedSections.add(entry.target.dataset.id);
      }
    }
  }
}
</script>

Производительность и оптимизация

  • once: true экономит ресурсы, если элемент нужно отследить только один раз.
  • threshold с массивом значений позволяет создавать более гибкие триггеры для анимаций, например, по частям элемента.
  • Отслеживание нескольких элементов одним observer. Можно использовать общий обработчик для группы элементов, минимизируя количество создаваемых объектов IntersectionObserver.
<div v-for="item in items" :key="item.id"
     v-intersection-observer="{ handler: handleMultiple, once: true }">
  {{ item.name }}
</div>

<script>
export default {
  methods: {
    handleMultiple({ entry }) {
      if (entry.isIntersecting) {
        console.log('Появился элемент:', entry.target.textContent);
      }
    }
  }
}
</script>

Совместимость и тонкости

  • Директива работает только в браузерах, поддерживающих Intersection Observer API (современные версии Chrome, Firefox, Safari, Edge).
  • SSR и prerendering: при серверной генерации контента элементы не видимы, поэтому обработчики срабатывают только на клиенте.
  • Динамические изменения DOM: при добавлении новых элементов после инициализации наблюдателя, их нужно снова регистрировать с v-intersection-observer.

Вывод

v-intersection-observer предоставляет удобный реактивный способ отслеживания видимости элементов в Quasar. Сочетая опции конфигурации и обработчики, можно реализовать ленивую загрузку, плавные анимации, сбор аналитики и другие эффекты, не нагружая производительность страницы.

Ключевое преимущество — простота интеграции с Vue.js и возможность использовать стандартные возможности Intersection Observer без лишнего кода.