大致步骤:
- 准备carousel组件基础布局,全局注册
- 写内部逻辑代码
- 向外暴露轮播的数据、自动轮播间隔时长和自动轮播属性
- 自动播放,设置了就自动轮播
- 如果有自动播放,鼠标进入离开,暂停,开启
- 指示器切换,上一张,下一张
- 销毁组件,清理定时器
代码实现 轮播图基础结构和逻辑
<div class='carousel' @mouseenter="stop()" @mouseleave="start()">
<ul class="carousel-body">
<li class="carousel-item" v-for="(item,i) in sliders" :key="item.id" :class="{fade:index===i}">
<RouterLink to="/">
<img :src="item.imgUrl" alt="">
</RouterLink>
</li>
</ul>
<a @click="toggle(-1)" href="javascript:;" class="carousel-btn prev"><i class="iconfont icon-angle-left"></i></a>
<a @click="toggle(1)" href="javascript:;" class="carousel-btn next"><i class="iconfont icon-angle-right"></i></a>
<div class="carousel-indicator">
<span v-for="(item,i) in sliders" :key="i" :class="{active:index===i}"></span>
</div>
</div>
</template>
<script>
import { onUnmounted, ref,watch } from 'vue'
export default {
name: 'Carousel',
//数据 间隔时长 自动播放
props:{
sliders:{
type:Array,
default:()=>[]
},
duration: {
type: Number,
default: 3000
},
autoPlay: {
type: Boolean,
default: false
}
},
setup(props){
let index =ref(0)
let timer=null
//1.自动播放
const autoPlay=()=>{
clearInterval(timer)
timer=setInterval(()=>{
index.value++
if(index.value >= props.sliders.length){
index.value=0
}
},props.duration)
}
watch(()=>props.sliders,(newVal)=>{
// 判断:当slider有数据且是auto时 自动播放
if(newVal.length && props.autoPlay){
index.value = 0
autoPlay();
}
},{immediate:true})
//2.鼠标进入离开,暂停,开启
const stop=()=>{
if(timer) clearInterval(timer)
}
const start=()=>{
// 判断:当slider有数据且是auto时 自动播放
if(props.sliders.length && props.autoPlay){
autoPlay();
}
}
//3.指示器切换,上一张,下一张,圆点切换
const toggle=(step)=>{
let newIndex=index.value+step
//判断 超出范围
if(newIndex>=props.sliders.length){
index.value=0
return
}
if(newIndex<0){
index.value=props.sliders.length-1
return
}
//正常
index.value=newIndex
}
//4.销毁组件,清理定时器
onUnmounted(()=>{
setInterval(timer)
})
return {index,stop,start,toggle}
}
}
</script>
<style scoped lang="less">
.carousel{
width: 100%;
height: 100%;
min-width: 300px;
min-height: 150px;
position: relative;
.carousel{
&-body {
width: 100%;
height: 100%;
}
&-item {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
opacity: 0;
transition: opacity 0.5s linear;
&.fade {
opacity: 1;
z-index: 1;
}
img {
width: 100%;
height: 100%;
}
}
&-indicator {
position: absolute;
left: 0;
bottom: 20px;
z-index: 2;
width: 100%;
text-align: center;
span {
display: inline-block;
width: 12px;
height: 12px;
background: rgba(0,0,0,0.2);
border-radius: 50%;
cursor: pointer;
~ span {
margin-left: 12px;
}
&.active {
background: #fff;
}
}
}
&-btn {
width: 44px;
height: 44px;
background: rgba(0,0,0,.2);
color: #fff;
border-radius: 50%;
position: absolute;
top: 228px;
z-index: 2;
text-align: center;
line-height: 44px;
opacity: 0;
transition: all 0.5s;
&.prev{
left: 20px;
}
&.next{
right: 20px;
}
}
}
&:hover {
.carousel-btn {
opacity: 1;
}
}
}
</style>
全局注册轮播图:新建一个index.js文件,导入组件
import Carousel from "./xtx-carousel.vue";
export default {
install(app) {
app.component(Carousel.name, Carousel);
},
};
在项目入口文件导入index.js: import UI from "./components/library"; createApp(App).use(store).use(router).use(UI).mount('#app')
需要用到组件直接使用组件即可