Посібник для Vue
Дізнайтеся, як будувати слайдери з @reelkit/vue.
Базовий слайдер
The <Reel> загортає контролер слайдера з ядра. Використовуйте слот #item щоб рендерити кожен слайд із віртуалізацією — монтуються лише видимі слайди.
<script setup lang="ts">
import { Reel, ReelIndicator } from '@reelkit/vue';
const items = [
{ title: 'Virtualized', subtitle: 'Only 3 slides in DOM', color: '#6366f1' },
{ title: 'Touch First', subtitle: 'Native swipe gestures', color: '#8b5cf6' },
{ title: 'Zero Deps', subtitle: 'Tiny bundle size', color: '#7c3aed' },
{ title: 'Keyboard Nav', subtitle: 'Full a11y support', color: '#ec4899' },
{ title: 'SSR Ready', subtitle: 'Works everywhere', color: '#14b8a6' },
{ title: '60fps', subtitle: 'Smooth animations', color: '#f59e0b' },
];
const onAfterChange = (index: number) => {
console.log('Current index:', index);
};
</script>
<template>
<Reel
:count="items.length"
style="width: 100%; height: 100dvh"
direction="vertical"
:enable-wheel="true"
@after-change="onAfterChange"
>
<template #item="{ index, size }">
<div
:style="{
width: size[0] + 'px',
height: size[1] + 'px',
background: items[index].color,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
color: '#fff',
}"
>
<div style="font-size: 1.5rem; font-weight: bold">
{{ items[index].title }}
</div>
<div style="font-size: 0.875rem; opacity: 0.8">
{{ items[index].subtitle }}
</div>
</div>
</template>
<div style="position: absolute; right: 12px; top: 50%; transform: translateY(-50%); z-index: 10">
<ReelIndicator direction="vertical" />
</div>
</Reel>
</template>ReelIndicator
Необов’язковий компонент, що показує індикатори прогрес у в стилі Instagram із поточною позицією в слайдері. Якщо він усередині <Reel>, він сам під’єднується до count та active значення через provide/inject у Vue — нічого зв’язувати вручну не треба.
<!-- Auto-connect: count and active are inherited from parent Reel -->
<Reel :count="10" :size="[400, 600]">
<template #item="{ index, size }"> ... </template>
<ReelIndicator direction="vertical" />
</Reel>
<!-- Manual usage: pass count and active explicitly (e.g. outside a Reel) -->
<ReelIndicator :count="10" :active="currentIndex" />Імперативний API — шаблонний ref
The <Reel> надає інтерфейс ReelExpose через шаблонний ref. Скористайтеся ref() щоб зберегти посилання й викликати імперативні методи на кшталт next(), prev(), та goTo().
<script setup lang="ts">
import { ref } from 'vue';
import { Reel, type ReelExpose } from '@reelkit/vue';
const items = [
{ title: 'Slide 1', color: '#6366f1' },
{ title: 'Slide 2', color: '#8b5cf6' },
{ title: 'Slide 3', color: '#ec4899' },
];
const sliderRef = ref<ReelExpose | null>(null);
const currentIndex = ref(0);
const onAfterChange = (index: number) => {
currentIndex.value = index;
};
</script>
<template>
<Reel
ref="sliderRef"
:count="items.length"
style="width: 100%; height: 100dvh"
direction="vertical"
:enable-wheel="true"
@after-change="onAfterChange"
>
<template #item="{ index, size }">
<div
:style="{
width: size[0] + 'px',
height: size[1] + 'px',
}"
>
{{ items[index].title }}
</div>
</template>
</Reel>
<div style="position: absolute; bottom: 16px; left: 50%; transform: translateX(-50%)">
<button
:disabled="currentIndex === 0"
@click="sliderRef?.prev()"
>
Prev
</button>
<button
:disabled="currentIndex === items.length - 1"
@click="sliderRef?.next()"
>
Next
</button>
<button @click="sliderRef?.goTo(2)">Go to 3</button>
</div>
</template>Горизонтальний напрямок
Set direction="horizontal" для слайдера зі свайпом ліворуч і праворуч. Напрямок індикатора має збігатися.
<Reel
:count="items.length"
:size="[400, 300]"
direction="horizontal"
>
<template #item="{ index, size }">
<div :style="{ width: size[0] + 'px', height: size[1] + 'px' }">
{{ items[index].title }}
</div>
</template>
<ReelIndicator direction="horizontal" />
</Reel>Auto-sizing
The size необов’язковий. Якщо його не передати, <Reel> сам вимірює свій к онтейнер через ResizeObserver і підлаштовується під макет, заданий CSS. Розмір контейнера має задавати батьківський елемент — наприклад, flex, grid або явні розміри в CSS.
<!-- Explicit size (fixed) -->
<Reel :count="items.length" :size="[400, 600]">
<template #item="{ index, size }"> ... </template>
</Reel>
<!-- Auto-size (responsive — sized by CSS) -->
<Reel :count="items.length" style="width: 100%; height: 100dvh">
<template #item="{ index, size }"> ... </template>
</Reel>Переходи
Передайте пропс transition щоб змінити анімацію слайдів. ReelKit має п’ять переходів, які піддаються tree-shaking: slideTransition (типово), fadeTransition, flipTransition, cubeTransition, та zoomTransition.
<script setup lang="ts">
import { Reel, cubeTransition } from '@reelkit/vue';
</script>
<template>
<Reel
:count="items.length"
:size="[400, 600]"
:transition="cubeTransition"
>
<template #item="{ index, size }"> ... </template>
</Reel>
</template>Режим циклу
Увімкніть нескінченну кругову навігацію пропсом loop . Слайдер безшовно переходить з останнього слайда на перший і навпаки.
<Reel
:count="items.length"
:size="[400, 600]"
:loop="true"
>
<template #item="{ index, size }"> ... </template>
</Reel>Колбеки подій
The <Reel> видає кілька подій для відстеження стану слайдера:
<script setup lang="ts">
import { Reel } from '@reelkit/vue';
const onBeforeChange = (index: number, nextIndex: number, rangeIndex: number) => {
console.log('Transitioning from', index, 'to', nextIndex);
};
const onAfterChange = (index: number, rangeIndex: number) => {
console.log('Arrived at slide', index);
};
const onSlideDragStart = (index: number) => {
console.log('Started dragging slide', index);
};
const onSlideDragEnd = (index: number) => {
console.log('Stopped dragging slide', index);
};
</script>
<template>
<Reel
:count="20"
style="width: 100%; height: 100dvh"
@before-change="onBeforeChange"
@after-change="onAfterChange"
@slide-drag-start="onSlideDragStart"
@slide-drag-end="onSlideDragEnd"
>
<template #item="{ index, size }"> ... </template>
</Reel>
</template>Навігація
Вбудовані способи навігації:
- Дотик / свайп: Тягніть, щоб гортати — з інерцією та прилипанням
- Клавіатура: Стрілки та Escape
- Колесо миші: Увімкніть
:enable-wheel="true" - Програмно: Використовуйте шаблонний ref, щоб дістатися
next(),prev(),goTo()
<script setup lang="ts">
import { ref } from 'vue';
import { Reel, type ReelExpose } from '@reelkit/vue';
const sliderRef = ref<ReelExpose | null>(null);
</script>
<template>
<Reel
ref="sliderRef"
:count="10"
:size="[400, 600]"
>
<template #item="{ index, size }">
<div :style="{ width: size[0] + 'px', height: size[1] + 'px' }">
Slide {{ index + 1 }}
</div>
</template>
</Reel>
<button @click="sliderRef?.prev()">Prev</button>
<button @click="sliderRef?.next()">Next</button>
<button @click="sliderRef?.goTo(5)">Go to 6</button>
</template>Стан в URL
useOverlayUrlState будує контролер стану в URL для оверлея й повертає його цілком, а ви передаєте його в <LightboxUrlOverlay> як його :controller . Стан відкриття належить адресному рядку, тож прив’язаний оверлей відкривається сам, а посилання — звичайний спосіб його відкрити. Перший запис відсутнього параметра додає один запис в історію, кожен наступний його замінює, тож гортання ніколи не ховає кнопку «назад». Тримайте контролер, щоб читати value/позицією і закривати програмно через set(null), the same low-level write the overlay uses internally on slide change.
<script setup lang="ts">
import { LightboxUrlOverlay, type LightboxItem } from '@reelkit/vue-lightbox';
import { useOverlayUrlState, urlIndexKey } from '@reelkit/vue';
const props = defineProps<{ images: LightboxItem[] }>();
const photo = useOverlayUrlState({
param: 'photo',
...urlIndexKey(() => props.images.length),
});
</script>
<template>
<!-- Opening is a link — the overlay reads the URL and opens itself. -->
<RouterLink v-for="(img, i) in props.images" :key="img.src" :to="`?photo=${i}`">
<img :src="img.src" />
</RouterLink>
<LightboxUrlOverlay :controller="photo" :items="props.images" />
</template>Об’єкт опцій приймає param, codec, та locator (усі три обов’язкові) плюс необов’язковий adapter. The codec та locator — узгоджена пара з однаковим Id, so for a plain ?photo=3 галереї розгортайте ...urlIndexKey(() => props.images.length), який повертає обидві половини одразу. urlIndexKey зіставляє параметр з індексом слайда й обмежує його живою кількістю, яку повертає геттер, тож застарілий або позамежний ?photo=99 відхиляється й сам зникає з URL замість того, щоб відкрити слайд, якого ніхто не називав. Передавайте геттер, а не число: у Vue setup виконується один раз, тож захоплена довжина застаріла б, поки посторінкова стрічка росте. Він загортає createIndexLocator (половину-локатор) і поєднує його з indexCodec. Посторінкова стрічка або галерея з адресацією за ідентичністю передає власну узгоджену пару codec + locator . Повна таблиця опцій — у довіднику API для Vue.
Патерн слота #item
Замість render prop із React у Vue використов ується слот #item з областю видимості. Саме він дає віртуалізацію: монтуються лише видимі слайди. Область слота надає три властивості:
<template #item="{ index, indexInRange, size }">
<!--
index : number — absolute slide index (0 to count-1)
indexInRange : number — position in visible window (0, 1, or 2)
size : [number, number] — [width, height] of the container
-->
<MySlide
:data="items[index]"
:style="{ width: size[0] + 'px', height: size[1] + 'px' }"
/>
</template>Composables
@reelkit/vue дає композабли для типових сценаріїв з оверлеями:
<script setup lang="ts">
import { ref } from 'vue';
import { useBodyLock, useFullscreen, useReelContext } from '@reelkit/vue';
// Lock body scroll when an overlay is open
const isOpen = ref(true);
useBodyLock(isOpen);
// Fullscreen API with cross-browser support
const containerRef = ref<HTMLElement | null>(null);
const { isFullscreen, toggle } = useFullscreen({ elementRef: containerRef });
// Access parent Reel context (when inside a Reel)
const reelContext = useReelContext();
// reelContext?.index — active slide index signal
// reelContext?.count — total slide count signal
// reelContext?.goTo() — navigate programmatically
// Bridge a core Subscribable into a reactive Vue ref
import { toVueRef } from '@reelkit/vue';
const index = toVueRef(reelContext!.index); // Ref<number> — re-renders on change
</script>Головне
- Composition API
Import
Reel,ReelIndicator, and composables directly into your<script setup>— реєструвати плагін не потрібно - слот #item з областю видимості
Відповідник у Vue для пропса
itemBuilderіз React — дає віртуалізацію звичним синтаксисом шаблонів - Шаблонний ref
Використовуйте
ref<ReelExpose>()для імперативної навігації — колбеки подій не потрібні - @after-change
Emits
(index, rangeIndex)— стежить за поточним індексом для оновлення інтерфейсу - контекст provide/inject
ReelIndicatorсам під’єднується до батьківськогоReelчерез provide/inject у Vue — жодного протягування пропсів вручну
Поради щодо продуктивності
- Тримайте шаблони слайдів легкими
The
#itemвиконується для кожного видимого слайда (зазвичай трьох одночасно). Уникайте важких обчислень і глибоко вкладених структур усередині. - Вантажте дані ближче до краю
Використовуйте
@after-changeщоб помітити наближення до кінця й підвантажити наступний пакет, доки слайди не скінчилися — так виходить нескінченна стрічка. - Тримайте імперативний стан у ref
Зберігайте посилання
ReelExposeта поточний індекс уref()Vue — це дає точкову реактивність без зайвих перерендерів. - Вимикайте колесо на сторінках із прокручуванням
Set
:enable-wheel="false"коли слайдер вбудований у макет із прокручуванням, щоб не перехоплювати прокручування сторінки.
Наступні кроки
- Довідник API для Vue - усі пропси, події та композабли
- Посібник з ядра - рушій без прив’язки до фреймворку
- Reel Player - відеоплеєр у стилі TikTok / ReelsReel Player - відеоплеєр у стилі TikTok / ReelsReel Player - відеоплеєр у стилі TikTok / Reels
- Lightbox - галерея зображень і відеоLightbox - галерея зображень і відеоLightbox - галерея зображень і відео