<template>
<el-button @click="dialogVisible = true">打开弹窗</el-button>
<el-dialog v-model="dialogVisible" title="滚动示例" width="400px" @opened="onDialogOpened">
<div v-if="buyInfo.length">
<Swiper
:key="swiperKey"
ref="swiperRef"
:autoplay="{ delay: 2000, disableOnInteraction: false }"
:direction="'vertical'"
:slides-per-view="4"
:spaceBetween="10"
:loop="true"
:modules="[Autoplay]"
style="width: 100%; height: 200px"
@swiper="onSwiper"
>
<SwiperSlide v-for="(item, index) in buyInfo" :key="item + '-' + index">
<div class="scroll-item" style="height: 100%; display: flex; align-items: center; justify-content: center;">
{{ item }}
</div>
</SwiperSlide>
</Swiper>
</div>
</el-dialog>
</template>
<script setup>
import { ref, watch, nextTick } from 'vue'
import { Swiper, SwiperSlide } from 'swiper/vue'
import { Autoplay } from 'swiper/modules'
import {ElButton ,ElDialog} from'element-plus'
import 'swiper/swiper-bundle.css'
import 'swiper/css'
import 'swiper/css/autoplay'
import 'element-plus/dist/index.css'
const dialogVisible = ref(false)
const buyInfo = ref([])
const swiperRef = ref(null)
const swiperKey = ref(0)
const onSwiper = (swiper) => {
swiperRef.value = swiper
}
// 模拟调用后端接口获取数据
const fetchData = () => {
setTimeout(() => {
buyInfo.value = Array.from({ length: 10 }, (_, i) => `Item ${i + 1}`)
}, 500)
}
// 每次弹窗打开都重新拉取数据
watch(dialogVisible, (val) => {
if (val) {
fetchData()
}
})
// 每次 buyInfo 变化,强制重建 Swiper
watch(buyInfo, () => {
swiperKey.value++;
}, { deep: true });
// 弹窗内容渲染后,激活 Swiper 自动滚动
const onDialogOpened = () => {
nextTick(() => {
if (swiperRef.value) {
swiperRef.value.autoplay.start()
}
})
}
</script>
使用的注意点
1.需要手动引入模块Autoplay
import { Autoplay } from 'swiper/modules'
2.在Swiper组件中使用
:modules="[Autoplay]"
注意点二:
当数据是后端接口获取的时候,Swiper 实例被重置或重新初始化
问题:第一次打开弹窗能够自动滚动,第二次打开弹窗无法自动滚动:
原因:fetchData 函数会重新获取数据,这可能导致 Swiper 实例被重置或未正确初始化。虽然代码中有 watch 监听 buyInfo 变化,但代码中需要添加更新的逻辑
解决如下:
let swiperKey=ref(0)
// 每次 buyInfo 变化(保存后端的数据的变量),强制重建 Swiper
watch(buyInfo, () => {
swiperKey.value++;
}, { deep: true });
简单效果图