vue实现小米轮播图
Vue实现小米轮播图
使用Vue实现类似小米官网的轮播图效果,可以通过以下步骤完成。示例基于Vue 3的Composition API和<script setup>语法。
核心实现思路
- 数据驱动:通过数组存储轮播图数据(图片URL、跳转链接等)。
- 自动轮播:使用
setInterval实现定时切换。 - 无缝衔接:通过复制首尾图片实现视觉无缝效果。
- 手势支持:添加
touchstart/touchmove事件实现滑动切换。
完整代码示例
<template>
<div class="slider-container"
@mouseenter="pauseAutoPlay"
@mouseleave="startAutoPlay">
<div class="slider-track"
:style="{ transform: `translateX(${-currentIndex * 100}%)` }"
@touchstart="handleTouchStart"
@touchmove="handleTouchMove"
@touchend="handleTouchEnd">
<div v-for="(item, index) in slides" :key="index" class="slide">
<img :src="item.image" :alt="item.title">
</div>
</div>
<div class="slider-dots">
<span v-for="(dot, index) in realSlides.length"
:key="index"
:class="{ active: currentIndex === index }"
@click="goToSlide(index)"></span>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
const slides = ref([
{ image: 'https://via.placeholder.com/800x400?text=Slide1', title: 'Slide1' },
{ image: 'https://via.placeholder.com/800x400?text=Slide2', title: 'Slide2' },
{ image: 'https://via.placeholder.com/800x400?text=Slide3', title: 'Slide3' }
]);
// 克隆首尾图片实现无缝滚动
const realSlides = ref([...slides.value]);
realSlides.value.unshift(slides.value[slides.value.length - 1]);
realSlides.value.push(slides.value[0]);
const currentIndex = ref(1);
let autoPlayTimer = null;
let touchStartX = 0;
let touchEndX = 0;
const startAutoPlay = () => {
autoPlayTimer = setInterval(() => {
nextSlide();
}, 3000);
};
const pauseAutoPlay = () => {
clearInterval(autoPlayTimer);
};
const nextSlide = () => {
currentIndex.value = (currentIndex.value + 1) % realSlides.value.length;
if (currentIndex.value === realSlides.value.length - 1) {
setTimeout(() => {
currentIndex.value = 1;
}, 500);
}
};
const prevSlide = () => {
currentIndex.value = (currentIndex.value - 1 + realSlides.value.length) % realSlides.value.length;
if (currentIndex.value === 0) {
setTimeout(() => {
currentIndex.value = realSlides.value.length - 2;
}, 500);
}
};
const goToSlide = (index) => {
currentIndex.value = index + 1;
};
const handleTouchStart = (e) => {
touchStartX = e.touches[0].clientX;
pauseAutoPlay();
};
const handleTouchMove = (e) => {
touchEndX = e.touches[0].clientX;
};
const handleTouchEnd = () => {
if (touchStartX - touchEndX > 50) {
nextSlide();
} else if (touchEndX - touchStartX > 50) {
prevSlide();
}
startAutoPlay();
};
onMounted(() => {
startAutoPlay();
});
onUnmounted(() => {
pauseAutoPlay();
});
</script>
<style scoped>
.slider-container {
position: relative;
width: 100%;
height: 400px;
overflow: hidden;
}
.slider-track {
display: flex;
height: 100%;
transition: transform 0.5s ease;
}
.slide {
flex: 0 0 100%;
}
.slide img {
width: 100%;
height: 100%;
object-fit: cover;
}
.slider-dots {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
display: flex;
gap: 8px;
}
.slider-dots span {
width: 10px;
height: 10px;
border-radius: 50%;
background: rgba(255,255,255,0.5);
cursor: pointer;
}
.slider-dots span.active {
background: #fff;
}
</style>
关键实现细节
无缝滚动技术
- 在数组首尾分别添加克隆的最后一幅和第一幅图片
- 当滚动到克隆图片时,通过
setTimeout立即跳转到真实图片位置
自动轮播控制
onMounted时启动定时器,onUnmounted时清除- 鼠标悬停时暂停轮播,离开时恢复
触摸事件处理
- 记录触摸起始和结束位置的X坐标
- 根据滑动距离判断切换方向(左滑下一张/右滑上一张)
进阶优化建议
-
响应式适配
@media (max-width: 768px) { .slider-container { height: 200px; } } -
懒加载图片
<img v-lazy="item.image" :alt="item.title"> -
过渡动画增强
.slider-track { transition: transform 0.5s cubic-bezier(0.25, 0.1, 0.25, 1); } -
无限循环优化
// 替代简单的取模运算 if (currentIndex.value >= realSlides.value.length - 1) { currentIndex.value = 1; } if (currentIndex.value <= 0) { currentIndex.value = realSlides.value.length - 2; }
注意事项
- 图片路径需替换为实际项目资源
- 移动端需添加
touch-action: pan-y样式防止浏览器默认行为干扰 - 对于Vue 2版本,需将Composition API改为Options API写法







