You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue3中Swiper9自定义切换按钮图片不随幻灯片更新问题排查

问题:Vue3 + Swiper9轮播导航按钮图片切换不更新

在Vue3项目中使用Swiper9实现轮播组件,希望上一页按钮显示上一张幻灯片的图片,下一页按钮显示下一张幻灯片的图片,且图片随幻灯片切换实时更新。目前按钮初始图片显示正常,但切换幻灯片时图片无法更新。

原代码(Home.vue)

<template>
    <div class="testimonial-slider">
      <swiper :navigation="true" :modules="modules" class="mySwiper">
        <swiper-slide v-for="(testimonial, index) in testimonials" :key="index">
          <div class="testimonial">
            <p>{{ testimonial.text }}</p>
            <div class="profile-info">
              <div class="profile-image">
                <img :src="testimonial.image" alt="">
              </div>
              <div class="profile-text">
                <p class="name">{{ testimonial.name }}</p>
                <p class="profession">{{ testimonial.profession }}</p>
              </div>
            </div>
          </div>
        </swiper-slide>
        <div class="swiper-navigation flex flex-row gap-12 justify-between">
          <div class="swiper-prev">
            <div class="image-container">
              <img :src="testimonials[currentIndex - 1 >= 0 ? currentIndex - 1 : testimonials.length - 1].image" alt="">
            </div>
            <div class="overlay"></div>
          </div>
          <div class="swiper-next">
            <div class="image-container">
              <img :src="testimonials[(currentIndex + 1) % testimonials.length].image" alt="">
            </div>
            <div class="overlay"></div>
          </div>
        </div>
      </swiper>
    </div>
  </template>

<script>
  // Import Swiper Vue.js components
  import { Swiper, SwiperSlide } from 'swiper/vue';

  // Import Swiper styles
  import 'swiper/css';

  import 'swiper/css/navigation';
  import { Navigation } from 'swiper';

 export default {
    name: "Home",
    components: {
      Swiper,
      SwiperSlide,
    },
    data() {
      return {
        testimonials: [
          {
            text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris vestibulum vulputate massa, et efficitur nisl bibendum at.',
            image: 'assets/images/1-logo.svg',
            name: 'John Doe',
            profession: 'CEO',
          },
          {
            text: 'In ac lacus eu ex commodo vestibulum. Donec eleifend commodo neque, nec efficitur erat maximus sed.',
            image: 'assets/images/2-logo.svg',
            name: 'Jane Smith',
            profession: 'CFO',
          },
          {
            text: 'Suspendisse in vestibulum erat. Morbi non neque nec dolor dignissim lacinia ac vel orci.',
            image: 'assets/images/3-logo.svg',
            name: 'Bob Johnson',
            profession: 'CTO',
          },
          {
            text: 'Vestibulum eu dolor ac felis vehicula dictum. Duis eget volutpat sapien. Aliquam tincidunt ipsum eget tellus posuere, id rhoncus erat convallis.',
            image: 'assets/images/4-logo.jpg',
            name: 'Emily Thompson',
            profession: 'Marketing Director',
          },
        ],
        currentIndex: 0,
      };
    },
    setup() {
      return {
        modules: [Navigation],
      };
    },
    mounted() {
      this.$nextTick(() => {
        this.$refs.swiper.$swiper.on('slideChange', () => {
          this.currentIndex = this.$refs.swiper.$swiper.realIndex;
        });
      });
    },
  };
</script>

<style scoped>

</style>

问题原因及解决方案

核心问题1:未给Swiper组件添加ref属性

原代码中mounted钩子尝试通过this.$refs.swiper获取Swiper实例,但模板里的<swiper>标签没有添加ref="swiper",导致事件无法绑定,currentIndex不会随幻灯片切换更新,按钮图片自然不会变化。

核心问题2:事件绑定方式冗余(可选优化)

直接使用Swiper Vue组件提供的@slideChange事件比手动绑定原生Swiper实例事件更简洁可靠,无需依赖$nextTick。

修正后的代码

<template>
  <div class="testimonial-slider">
    <!-- 添加ref属性,绑定slideChange事件 -->
    <swiper 
      ref="swiper" 
      :navigation="true" 
      :modules="modules" 
      class="mySwiper"
      @slideChange="onSlideChange"
    >
      <swiper-slide v-for="(testimonial, index) in testimonials" :key="index">
        <div class="testimonial">
          <p>{{ testimonial.text }}</p>
          <div class="profile-info">
            <div class="profile-image">
              <img :src="testimonial.image" alt="">
            </div>
            <div class="profile-text">
              <p class="name">{{ testimonial.name }}</p>
              <p class="profession">{{ testimonial.profession }}</p>
            </div>
          </div>
        </div>
      </swiper-slide>
    </swiper>
    <!-- 把自定义导航按钮移到Swiper外部,避免内部结构干扰 -->
    <div class="swiper-navigation flex flex-row gap-12 justify-between">
      <div class="swiper-prev">
        <div class="image-container">
          <img :src="testimonials[currentIndex - 1 >= 0 ? currentIndex - 1 : testimonials.length - 1].image" alt="">
        </div>
        <div class="overlay"></div>
      </div>
      <div class="swiper-next">
        <div class="image-container">
          <img :src="testimonials[(currentIndex + 1) % testimonials.length].image" alt="">
        </div>
        <div class="overlay"></div>
      </div>
    </div>
  </div>
</template>

<script>
import { Swiper, SwiperSlide } from 'swiper/vue';
import 'swiper/css';
import 'swiper/css/navigation';
import { Navigation } from 'swiper';

export default {
  name: "Home",
  components: {
    Swiper,
    SwiperSlide,
  },
  data() {
    return {
      testimonials: [
        {
          text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris vestibulum vulputate massa, et efficitur nisl bibendum at.',
          image: 'assets/images/1-logo.svg',
          name: 'John Doe',
          profession: 'CEO',
        },
        {
          text: 'In ac lacus eu ex commodo vestibulum. Donec eleifend commodo neque, nec efficitur erat maximus sed.',
          image: 'assets/images/2-logo.svg',
          name: 'Jane Smith',
          profession: 'CFO',
        },
        {
          text: 'Suspendisse in vestibulum erat. Morbi non neque nec dolor dignissim lacinia ac vel orci.',
          image: 'assets/images/3-logo.svg',
          name: 'Bob Johnson',
          profession: 'CTO',
        },
        {
          text: 'Vestibulum eu dolor ac felis vehicula dictum. Duis eget volutpat sapien. Aliquam tincidunt ipsum eget tellus posuere, id rhoncus erat convallis.',
          image: 'assets/images/4-logo.jpg',
          name: 'Emily Thompson',
          profession: 'Marketing Director',
        },
      ],
      currentIndex: 0,
      modules: [Navigation] // 把modules移到data,避免混合API写法
    };
  },
  methods: {
    // 定义slideChange事件处理函数,更新currentIndex
    onSlideChange() {
      this.currentIndex = this.$refs.swiper.$swiper.realIndex;
    }
  }
};
</script>

<style scoped>
/* 可根据需求添加导航按钮样式 */
.swiper-navigation {
  margin-top: 20px;
}
.swiper-prev, .swiper-next {
  cursor: pointer;
}
.image-container img {
  width: 60px;
  height: 60px;
  border-radius: 50%;
}
</style>

额外说明

  • 如果需要保留Swiper默认的导航按钮并同时使用自定义图片按钮,可以通过Swiper的navigation配置指定自定义按钮的选择器,避免冲突。
  • 确保testimonials数组中的图片路径正确,避免因路径问题导致图片不显示。

内容的提问来源于stack exchange,提问作者user19367608

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 07:27:06