v-scroll

v-scroll в Vuetify представляет собой директиву и набор утилит для отслеживания и управления прокруткой элементов на странице. Она позволяет создавать динамическое поведение интерфейса при прокрутке, реагировать на позиции скролла, реализовывать эффекты «прилипания» элементов и оптимизировать отображение больших списков.


Основные возможности

  1. Отслеживание позиции скролла Директива v-scroll позволяет получать текущую позицию вертикальной и горизонтальной прокрутки элемента или окна. Применяется как к отдельным контейнерам, так и к глобальному окну window.

    <template>
      <div v-scroll="onScroll" style="height: 300px; overflow-y: auto;">
        <div style="height: 1000px;"></div>
      </div>
    </template>
    
    <script>
    export default {
      methods: {
        onScroll(e) {
          console.log('Scroll position:', e.target.scrollTop);
        }
      }
    }
    </script>

    Здесь e.target.scrollTop возвращает текущую вертикальную позицию прокрутки.

  2. Реактивные переменные для скролла С помощью Composition API можно связывать позицию прокрутки с реактивными переменными:

    <template>
      <div v-scroll="updateScroll" style="height: 400px; overflow-y: auto;">
        <div style="height: 1200px;"></div>
      </div>
      <p>Текущая позиция: {{ scrollY }}</p>
    </template>
    
    <script>
    import { ref } from 'vue';
    
    export default {
      setup() {
        const scrollY = ref(0);
    
        function updateScroll(e) {
          scrollY.value = e.target.scrollTop;
        }
    
        return { scrollY, updateScroll };
      }
    }
    </script>

    Такой подход позволяет динамически изменять состояние интерфейса в зависимости от позиции скролла.


Использование с окнами браузера

Для отслеживания прокрутки всего окна используется модификация с window:

<template>
  <div>
    <v-btn :class="{ 'elevated-btn': scrolled }">Наверх</v-btn>
  </div>
</template>

<script>
import { ref, onMounted, onUnmounted } from 'vue';

export default {
  setup() {
    const scrolled = ref(false);

    const handleScroll = () => {
      scrolled.value = window.scrollY > 100;
    };

    onMounted(() => window.addEventListener('scroll', handleScroll));
    onUnmounted(() => window.removeEventListener('scroll', handleScroll));

    return { scrolled };
  }
};
</script>

<style>
.elevated-btn {
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}
</style>

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


Плавная прокрутка с v-scroll-to

Vuetify предоставляет функциональность для программной прокрутки к конкретным элементам через утилиту v-scroll-to или JavaScript API:

<template>
  <v-btn @click="scrollToSection">Перейти к секции</v-btn>
  <div style="height: 800px;"></div>
  <div ref="targetSection">Целевая секция</div>
</template>

<script>
import { ref } from 'vue';

export default {
  setup() {
    const targetSection = ref(null);

    const scrollToSection = () => {
      targetSection.value.scrollIntoView({ beh * avior: 'smooth' });
    };

    return { targetSection, scrollToSection };
  }
};
</script>

Использование scrollIntoView с beh * avior: 'smooth' обеспечивает плавную анимацию прокрутки без сторонних библиотек.


Эффекты «прилипания» и видимость элементов

С помощью v-scroll можно реализовать эффекты sticky элементов, а также динамически показывать или скрывать элементы при скролле:

<template>
  <div v-scroll="checkVisibility" style="height: 500px; overflow-y: auto;">
    <div style="height: 1000px;">
      <v-alert v-if="visible" type="success">Элемент виден!</v-alert>
    </div>
  </div>
</template>

<script>
import { ref } from 'vue';

export default {
  setup() {
    const visible = ref(false);

    const checkVisibility = (e) => {
      visible.value = e.target.scrollTop > 200;
    };

    return { visible, checkVisibility };
  }
};
</script>

Такой подход полезен для уведомлений, подсветки меню или запуска анимаций при прокрутке.


Оптимизация больших списков

При работе с длинными списками v-scroll помогает реализовать ленивую загрузку или виртуальный скролл. Вместе с v-for можно подгружать элементы по мере прокрутки, уменьшая нагрузку на DOM:

<template>
  <div v-scroll="loadMore" style="height: 400px; overflow-y: auto;">
    <v-list>
      <v-list-item v-for="item in items" :key="item.id">{{ item.text }}</v-list-item>
    </v-list>
  </div>
</template>

<script>
import { ref } from 'vue';

export default {
  setup() {
    const items = ref(Array.from({ length: 20 }, (_, i) => ({ id: i, text: `Элемент ${i}` })));

    const loadMore = (e) => {
      const bottom = e.target.scrollHeight - e.target.scrollTop === e.target.clientHeight;
      if (bottom) {
        const nextItems = Array.from({ length: 10 }, (_, i) => ({ id: items.value.length + i, text: `Элемент ${items.value.length + i}` }));
        items.value.push(...nextItems);
      }
    };

    return { items, loadMore };
  }
};
</script>

Такое решение снижает потребление памяти и делает интерфейс отзывчивым даже при тысячах элементов.


Советы по производительности

  • Для крупных списков рекомендуется использовать v-virtual-scroll вместо обычного v-scroll.
  • Ограничивать количество обработчиков события scroll и использовать throttle или debounce для предотвращения излишнего обновления состояния.
  • Для элементов с анимацией применять transform и opacity, чтобы избежать перерасчетов layout браузером.

v-scroll является гибким инструментом для управления прокруткой в интерфейсах Vuetify, позволяя создавать интерактивные, динамичные и оптимизированные пользовательские интерфейсы.