0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[swiper]画像の切り替えを行う際、navigationボタンを押下した時に、表示されている画像のテキストをボタン押下ごとに切り替える

Last updated at Posted at 2024-08-06

実際の現場で、swiperを使用して
画像の切り替えを行う際、navigationボタンを押下した時に、
表示されている画像のテキストも切り替える実装に
かなり苦戦したため、備忘録として記載します。

初めに

swiperとは何ぞやという人は、下記の公式ページを参照ください。
それぞれ目的の合ったリンクを確認するのが良いと思います。
Vueの場合:swiper Vue.js Components
Nuxtの場合:Swiper Nuxt Modules

本題

ここでは、3つのコンポーネントを使用して、
子→親→子という形で、defineProps及びdefineEmits
行います。
まず全体のソースコードはこちらになります。

親コンポーネント(index.vue)

/page/swiper/index.vue

<template>
  <div>
    <SwiperComponent @updateComment="updateComment" />
    <CommentDisplay :comment="currentComment"/>
  </div>
</template>
<script setup lang="ts">
import { ref } from 'vue';

const currentComment = ref<string>()

const updateComment = (newComment: string) => {
  currentComment.value = newComment
}
</script>
子コンポーネント(SwiperComponent.vue)

/components/SwiperComponent.vue

<template>
  <swiper 
    :modules="[Navigation]" 
    :slides-per-view="1"
    @slideChange="onSlideChange"
    :navigation="{
      nextEl: '.swiper-button-next',
      prevEl: '.swiper-button-prev'
    }"
  >
    <swiper-slide v-for="image in images" :key="image.id">
      <div>
        <img :src="image.src" :alt="'Image ' + image.id" />
      </div>
    </swiper-slide>
  </swiper>
  <div class="swiper-button-next"></div>
  <div class="swiper-button-prev"></div>
</template>

<script setup lang="ts">
import 'swiper/css';
import 'swiper/css/navigation';
import { Swiper, SwiperSlide } from 'swiper/vue';
import { Navigation } from 'swiper/modules';
import { onMounted, ref } from 'vue'

interface SwiperInstance {
  realIndex: number;
}

//data
const images = [
  {
    id: 1,
    src: 'assets\img\カワイクテゴメンネ.jpg',
    comment: 'This is the first image.'
  },
  {
    id: 2,
    src: 'assets\img\image_processing20200630-1-1rg32vr.jpg',
    comment: 'This is the second image.'
  },
  {
    id: 3,
    src: 'assets\img\IMG_3490-1024x683.jpg',
    comment: 'This is the third image.'
  }
];

const emit = defineEmits(['updateComment'])

const onSlideChange = (swiper: SwiperInstance) => {
  const currentComment = images[swiper.realIndex].comment
  emit('updateComment', currentComment)
}

// 初期描画時のコメントを取得する
onMounted(() => {
  emit('updateComment', images[0].comment)
})
</script>

<style scoped>
img {
  width: 100%;
  height: auto;
}

p {
  text-align: center;
  margin: 10px 0 0;
}

.swiper-button-next,
.swiper-button-prev {
  color: #000;
  cursor: pointer;
}
</style>

子コンポーネント(CommentDisplay.vue)

/components/CommentDisplay.vue

<template>
  <dev>
    <p>{{ props.comment }}</p>
  </dev>
</template>

<script setup lang="ts">
const props = defineProps<{
  comment: string | undefined
}>();
</script>

<style scoped>
p {
  text-align: center;
  margin: 10px 0 0;
}
</style>
1. 子コンポーネント(SwiperComponent.vue)について

子コンポーネントにswiperを実装しています

import 'swiper/css';
import 'swiper/css/navigation';
import { Swiper, SwiperSlide } from 'swiper/vue';
import { Navigation } from 'swiper/modules';

各swiperをインポートして、'swiper/modules'でナビゲーションのモジュールを設定する

<swiper 
    :modules="[Navigation]" 
    :slides-per-view="1"
    @slideChange="onSlideChange"
    :navigation="{
      nextEl: '.swiper-button-next',
      prevEl: '.swiper-button-prev'
    }"
  >
    <swiper-slide v-for="image in images" :key="image.id">
      <div>
        <img :src="image.src" :alt="'Image ' + image.id" />
      </div>
    </swiper-slide>
  </swiper>
  <div class="swiper-button-next"></div>
  <div class="swiper-button-prev"></div>

templateで実装する方法は上記の実装を行い、
:modules="[Navigation]で、ナビゲーションのモジュールを提供して
ナビゲーションボタンを使ってスライドを切り替える機能を提供しています。
:modules属性を設定して、使用するモジュールを指定し、ここでは[Navigation]を指定してナビゲーション機能を有効にしています。

:slides-per-view="1"は、一度表示されるスライドの数を指定します。
1と設定したことで、一度に1つのスライドが表示される設定になります。

:navigation="{ nextEl: '.swiper-button-next', prevEl: '.swiper-button-prev' }"は、カスタムナビゲーションボタンを設定します。
nextElprevElプロパティを使って、次へボタンと前へボタンの要素を指定します。
今回の場合、.swiper-button-next.swiper-button-prevはそれぞれ「次へ」ボタンと「前へ」ボタンのCSSセレクタを指します。
これにより、カスタムのナビゲーションボタンが機能するようになります。

const emit = defineEmits(['updateComment'])

const onSlideChange = (swiper: SwiperInstance) => {
  const currentComment = images[swiper.realIndex].comment
  emit('updateComment', currentComment)
}

onMounted(() => {
  emit('updateComment', images[0].comment)
})

onSlideChange関数の引数にswiper: SwiperInstanceを取得
SwiperInstanceの型定義は以下の設定にしておく
※ここでtypescriptの型を定義する

interface SwiperInstance {
  realIndex: number;
}

以下のコードで、swiper.realIndexを使って現在のスライドのインデックスを取得し、imagesの配列から対応するcommentを取得するようにする

const currentComment = images[swiper.realIndex].comment

最後にemitで親コンポーネントにcommentを送信する

emit('updateComment', currentComment)
2. 親コンポーネント(index.vue)について

updateCommentでemitされたコメントをnewCommentに引数として持たせ、
currentCommentrefにコメントを格納する

const currentComment = ref<string>()

const updateComment = (newComment: string) => {
  currentComment.value = newComment
}

<CommentDisplay :comment="currentComment"/>で別のコンポーネントにpropsする

<CommentDisplay :comment="currentComment"/>
3. 子コンポーネント(CommentDisplay.vue)について

親コンポーネントから渡されたpropsを設定し、<p>{{ props.comment }}</p>でコメントを表示する

<script setup lang="ts">
const props = defineProps<{
  comment: string | undefined
}>();
</script>

まとめ

ざっくりですが、swiperの仕組みが分かった経験でした
ほぼ実装コードはchatGPTに頼っての解決でしたが、chatGPTで的確な検索をするにはやはり知識を屈指して行うのが最短ルートだったなと感じました。
まだ分からないことも多々ありますが、自分自身で解決したことがとても嬉しいと感じたのが率直な感想です。
また、何かご指摘や誤った情報をしてしまっていましたらご指摘お願いいたします。。

公式の内容も確認しつつ行いましたが、ほぼchatGPTのおかげなので
今度は上手く調べられるようにしていきたいな、
(追伸. この実装を行うのに約3日くらいの時間を費やしたので今度はもう少し頑張りたい(´;ω;`))

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?