Vue गाइड

@reelkit/vue से स्लाइडर बनाना सीखें।

टच सबसे पहले
momentum और snap के साथ स्वाइप
कीबोर्ड नेविगेशन
तीर वाली कुंजियाँ + Escape
व्हील स्क्रॉल
वैकल्पिक, debounce के साथ
वर्चुअलाइज़्ड
10,000+ आइटम, DOM में 3
इंडिकेटर
Instagram जैसे खिसकते बिंदु
प्रोग्राम से API
template ref के ज़रिए next(), prev(), goTo()
लूप मोड
अनंत गोल नेविगेशन
दिशा
वर्टिकल या हॉरिज़ॉन्टल
Composition API
composables के साथ <script setup>

बुनियादी स्लाइडर

<Reel> कंपोनेंट core स्लाइडर कंट्रोलर को लपेटता है। वर्चुअलाइज़ेशन के साथ हर स्लाइड रेंडर करने के लिए #item slot इस्तेमाल करें — सिर्फ़ दिखने वाली स्लाइड mount होती हैं।

App.vue
<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> के अंदर रखने पर यह Vue के provide/inject के ज़रिए parent की count और active values से अपने-आप जुड़ जाता है — हाथ से जोड़ने की ज़रूरत नहीं।

vue-html
<!-- 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" />

Imperative API — टेम्पलेट ref

<Reel> कंपोनेंट template ref के ज़रिए ReelExpose इंटरफ़ेस देता है। reference रखने के लिए ref() इस्तेमाल करें और next(), prev() और goTo() जैसे imperative मेथड कॉल करें।

vue
<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>

क्षैतिज दिशा

बाएँ/दाएँ स्वाइप वाले स्लाइडर के लिए direction="horizontal" सेट करें। इंडिकेटर की दिशा भी इससे मेल खानी चाहिए।

vue-html
<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>

अपने-आप साइज़

size prop वैकल्पिक है। इसे छोड़ने पर <Reel> ResizeObserver से अपना कंटेनर खुद नापता है और CSS से तय लेआउट के हिसाब से ढल जाता है। कंटेनर का साइज़ उसके parent से तय होना चाहिए (जैसे flex, grid या तय CSS आकार)।

vue-html
<!-- 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 prop पास करें। ReelKit tree-shake होने वाले पाँच ट्रांज़िशन देता है: slideTransition (डिफ़ॉल्ट), fadeTransition, flipTransition, cubeTransition और zoomTransition।

vue
<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 prop से अनंत गोल नेविगेशन चालू करें। स्लाइडर आख़िरी स्लाइड से पहली पर (और उल्टा) बिना रुकावट लौट आता है।

vue-html
<Reel
  :count="items.length"
  :size="[400, 600]"
  :loop="true"
>
  <template #item="{ index, size }"> ... </template>
</Reel>

इवेंट callbacks

<Reel> कंपोनेंट स्लाइडर की स्टेट ट्रैक करने के लिए कई इवेंट emit करता है:

vue
<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>

नेविगेशन के बिल्ट-इन तरीके:

  • टच/स्वाइप: momentum और snap के साथ खींचकर आगे-पीछे जाएँ
  • कीबोर्ड: तीर वाली कुंजियाँ और Escape
  • माउस व्हील: :enable-wheel="true" से चालू करें
  • प्रोग्राम से: next(), prev(), goTo() तक पहुँचने के लिए template ref इस्तेमाल करें
vue
<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 किसी overlay के लिए URL-स्टेट कंट्रोलर बनाकर पूरा लौटाता है, फिर आप उसे <LightboxUrlOverlay> को उसके :controller prop के रूप में देते हैं। खुले होने की स्टेट address bar के पास है, इसलिए जुड़ा हुआ overlay खुद खुलता है और आम तौर पर लिंक ही उसे खोलता है। न मौजूद parameter का पहला write history में एक entry जोड़ता है और उसके बाद हर write उसे बदल देता है, इसलिए पेज बदलना back बटन को कभी दबाता नहीं। value/position पढ़ने और set(null) से प्रोग्राम से बंद करने के लिए कंट्रोलर रखें — यह वही निचले स्तर का write है जो overlay स्लाइड बदलने पर अंदर से करता है।

vue
<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>

विकल्पों का object param, codec और locator (तीनों ज़रूरी) लेता है, साथ में वैकल्पिक adapter। codec और locator एक ही Id साझा करने वाली मेल खाती जोड़ी हैं, इसलिए साधारण ?photo=3 गैलरी के लिए ...urlIndexKey(() => props.images.length) spread करें, जो दोनों हिस्से एक साथ लौटाता है। urlIndexKey parameter को स्लाइड index से जोड़ता है और उसे getter की लौटाई मौजूदा गिनती तक सीमित रखता है, इसलिए पुराना या सीमा से बाहर का ?photo=99 ठुकराया जाता है और कभी नाम न ली गई स्लाइड खोलने के बजाय URL से अपने-आप हट जाता है। संख्या नहीं, getter पास करें: Vue का setup एक ही बार चलता है, इसलिए पकड़ी गई लंबाई पेज वाली फ़ीड बढ़ने पर पुरानी पड़ जाएगी। यह createIndexLocator (locator वाला हिस्सा) को लपेटकर indexCodec के साथ जोड़ता है। पेज वाली फ़ीड या पहचान से key होने वाली गैलरी इसकी जगह अपनी मेल खाती codec + locator जोड़ी देती है। विकल्पों की पूरी तालिका Vue API रेफ़रेंस में है।

#item स्लॉट पैटर्न

React के render prop की जगह Vue #item scoped slot इस्तेमाल करता है। इससे वर्चुअलाइज़ेशन संभव होता है — सिर्फ़ दिखने वाली स्लाइड mount होती हैं। Slot scope तीन प्रॉपर्टी देता है:

vue-html
<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 overlay के आम मामलों के लिए composables देता है:

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

    Reel, ReelIndicator और composables को सीधे अपने <script setup> में import करें — किसी plugin को register करने की ज़रूरत नहीं

  • #item scoped slot

    React के itemBuilder prop का Vue वाला रूप — जाने-पहचाने template syntax के साथ वर्चुअलाइज़ेशन

  • Template ref

    imperative नेविगेशन के लिए ref<ReelExpose>() इस्तेमाल करें — इवेंट callbacks की ज़रूरत नहीं

  • @after-change

    (index, rangeIndex) emit करता है — UI अपडेट के लिए मौजूदा index पर नज़र रखें

  • provide/inject context

    ReelIndicator Vue के provide/inject से parent Reel से अपने-आप जुड़ता है — हाथ से props नीचे भेजने की ज़रूरत नहीं

परफ़ॉर्मेंस टिप्स

  • स्लाइड templates को हल्का रखें

    #item slot हर दिखने वाली स्लाइड के लिए चलता है (आम तौर पर एक बार में 3)। इसके अंदर भारी गणना या बहुत गहरी nested संरचना से बचें।

  • किनारे के पास डेटा लोड करें

    @after-change से पहचानें कि यूज़र आख़िर के पास पहुँच रहा है, और स्लाइड ख़त्म होने से पहले अगला बैच fetch करें — इससे अनंत स्क्रॉल वाली फ़ीड बनती है।

  • imperative स्टेट के लिए refs इस्तेमाल करें

    बेवजह दोबारा रेंडर के बिना बारीक reactivity के लिए ReelExpose reference और मौजूदा index को Vue के ref() में रखें।

  • स्क्रॉल होने वाले पेज में व्हील बंद करें

    जब स्लाइडर स्क्रॉल होने वाले लेआउट के अंदर हो, तो पेज का स्क्रॉल पकड़ने से बचने के लिए :enable-wheel="false" सेट करें।

अगले कदम

  • Vue API रेफ़रेंस - सभी props, इवेंट और composables
  • Core गाइड - फ़्रेमवर्क से स्वतंत्र इंजन
  • Reel Player - TikTok/Reels जैसा वीडियो प्लेयरReel Player - TikTok/Reels जैसा वीडियो प्लेयरReel Player - TikTok/Reels जैसा वीडियो प्लेयर
  • Lightbox - इमेज और वीडियो गैलरीLightbox - इमेज और वीडियो गैलरीLightbox - इमेज और वीडियो गैलरी