Vue 3(composition API)でカルーセルスライダーを作る方法

Vue.js

Vue.js V3(composition API)でカルーセルスライダーを作る方法を紹介します。

バニラJavaScriptでスライダーを作成する場合は、JavaScriptのスライダーのコードも参考にしてみてください。

Vue 3(composition API)でカルーセルスライダーを作る方法

ディレクトリ構成


root
├─ src
   ├─ App.vue
   ├─ main.js
   ├─ assets
   │   └─ img
   │      └─ 画像たち
   ├─ components
   │   ├─ Carousel.vue
   │   ├─ CarouselSlide.vue

今回触るのは、

  • App.vue
  • Carousel.vue
  • CarouselSlide.vue

の3つです。

App.vue

template

<div class="app">
  <Carousel
    @next="next"
    @prev="prev"
   >
    <CarouselSlide
      v-for="(slide, index) in slides"
      :key="slide"
      :index="index"
      :visibleSlide="visibleSlide"
      >
      <img :src="slide"/>
    </CarouselSlide>
  </Carousel>
</div>

まず、親コンポーネントであるApp.vueでは、2つのコンポーネントを入れ子にします。
Carouselからは、nextとprevというボタンのクリックイベントを受け取ります。

CarouselSlideでは、画像データをv-forでループして、表示できるようにpropsを渡します。
渡すものは、index番号と、現在表示しているものの番号です。

script

import Carousel from './components/Carousel.vue'
import CarouselSlide from './components/CarouselSlide.vue'
import { ref, computed } from 'vue'

export default {
  name: 'App',
  components: {
    Carousel,
    CarouselSlide,
  },
  setup() {

    const slides = ref([
    '画像',
    '画像',
    '画像',
    ...,
    ])

    // indexとイコールの変数を作成する
    const visibleSlide = ref(0)

    const slidesLength = computed(() => slides.value.length)

    // Carouselから受け取ったnext
    const next = () => {
      if(visibleSlide.value >= slidesLength.value - 1) {
        visibleSlide.value = 0
      } else {
        visibleSlide.value++
      }
    }
    // Carouselから受け取ったprev
    const prev = () => {
      if(visibleSlide.value <= 0) {
        visibleSlide.value = slidesLength.value - 1
      } else {
        visibleSlide.value--
      }
    }

    return {
      slides,
      visibleSlide,
      next,
      prev,
    }
  }

}

まず、コンポーネントをインポートします。
そして、refとcomputedを使うので、それらもインポートします。

そして、画像データをrefで登録して、リアクティブにします。
そのデータの数を取得しておきたいので、computedでLengthを計算した値を格納する変数を用意しておきます。

また、現在のスライドを示す変数も用意しておきます。

そして、Carousel.vueから受け取ったnextとprevというメソッドを設定します。
インデックス番号がデータの数、つまり画像数を表すので、それで条件分岐します。
最初か最後の場合と、そうでない場合で分岐して、
最初の場合は最後へ、最後の場合は最初へ移動するようにします。
最初か最後出ない場合は、1ずつ増やす、減らすという設定をすればいいです。

Carousel.vue

template

  <div class="carousel">
    <slot></slot>
    <button @click="next" class="carousel__next">次へ</button>
    <button @click="prev" class="carousel__prev">前へ</button>
  </div>

App.vueへ渡したいnextとprevメソッドを設定します。

script

export default {
  setup(props, context) {
    const next = () => {
      context.emit('next')
    }
    const prev = () => {
      context.emit('prev')
    }

    return {
      next,
      prev,
    }
  }
}

Vue 3で親コンポーネントへイベントやデータを渡したい場合、つまりemitしたい場合、setup(props,context)の2つ目の引数であるcontextを使います。
context.emit(eventName)を実行することで、親コンポーネントへ渡すことができます。

CarouselSlide.vue

template

  <div v-show="visibleSlide === index" class="carousel-slide">
    <slot></slot>
  </div>

親から受け取ったpropsを使います。
表示したいものは現在のスライドで、それはindexと同じものとすればOKです。

script

export default {
  props: [
    'visibleSlide',
    'index',
  ]
}

受け取るためのpropsを設定すればOKです。

Vue.js

Posted by devsakaso