实现的基本功能:
-
自动播放,暴露自动轮播属性,设置了就自动轮播
-
如果有自动播放,鼠标进入离开,暂停,开启
-
指示器切换,上一张,下一张
-
销毁组件,清理定时器
步骤:
1.实现通用轮播图样式的基本布局
2.设置为全局组件
3.设置业务组件
4.业务组件导入到首页当中(home.vue)
1)在src/components/library/Carousel.vue(这是轮播图的通用组件基本构建,全局注册)
<template>
<div class='xtx-carousel'>
<ul class="carousel-body">
<li class="carousel-item fade">
<RouterLink to="/">
<img src="http://yjy-xiaotuxian-dev.oss-cn-beijing.aliyuncs.com/picture/2021-04-15/1ba86bcc-ae71-42a3-bc3e-37b662f7f07e.jpg" alt=""> // 轮播图的位置
</RouterLink>
</li>
</ul>
// 轮播图的左侧的箭头
<a href="javascript:;" class="carousel-btn prev"><i class="iconfont icon-angle-left"></i></a>
// 轮播图的右侧箭头
<a href="javascript:;" class="carousel-btn next"><i class="iconfont icon-angle-right"></i></a>
// 轮播图的5个图中的小点点
<div class="carousel-indicator">
// v-for中可以写i 循环几次 可以学习一下
<span v-for="i in 5" :key="i"></span>
</div>
</div>
</template>
<script>
export default {
name: 'Carousel'
}
</script>
<style scoped lang="less">
.xtx-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>
2)全局注册轮播图 src/components/library/index.js
(注意:注册全局组件中单独设立js文件是为了好维护,Vue2中install函数中是Vue的构造函数,Vue3中是app是Vue的实例对象)
import Carousel from './Carousel.vue'
export default {
install (app) {
app.component(Carousel.name, Carousel)
}
}
然后在main.js中进行全局注册
3).构建首页轮播图的业务组件的基本布局 src/views/home/components/home-banner.vue
<template>
<div class="home-banner">
// 轮播图imgUrl的数组,然后传给通用组件轮播图 速度是2秒 启动自动播放
<Carousel :sliders="sliders" :duration="2" :autoplay="true"></Carousel>
</div>
</template>
<script>
import { findBanner } from '@/api/home.js'
import { ref } from 'vue'
export default {
name: 'HomeBanner',
setup() {
const sliders = ref([])
findBanner().then(res => { // 接口调用获取轮播图的集合Vue3中不使用async 与 await setup
函数使用很麻烦,而且步骤还是试验阶段,不建议使用,所以使用then
sliders.value = res.result
})
return { sliders } // 得到轮播图imgUrl的数组,然后传给通用组件轮播图
}
}
</script>
<style scoped lang="less">
.home-banner {
width: 1240px;
height: 500px;
position: absolute;
left: 0;
top: 0;
z-index: 98;
.xtx-carousel {
// 左侧箭头不应该在最左侧,需要在左侧导航的右边
::v-deep .carousel-btn.prev {
left: 270px;
}
// 5个小点点也是需要在左侧导航之外的中间部分
::v-deep .carousel-indicator {
padding-left: 250px;
}
}
}
</style>
实现功能已写在如下代码中
全部代码:
<template>
<div class="xtx-carousel">
<ul class="carousel-body">
<li
class="carousel-item "
v-for="(item, i) in sliders" // 轮播图的循环铺设
:key="item.id"
:class="{ fade: index === i }" // 添加了fade就会显现,index是几就会显示第几张图片
class:{}中是表达式
@mouseenter="stop" // 鼠标进入就停止的函数
@mouseleave="start" // 鼠标离开就继续播放轮播图的函数
>
<RouterLink to="/">
<img :src="item.imgUrl" alt="" /> // 轮播图的放置的地方
</RouterLink>
</li>
</ul>
// 轮播图的左箭头 点击与右箭头使用一个函数toggle,当中传入的值不同
<a href="#" @click="toggle(-1)" class="carousel-btn prev"><i class="iconfont icon-angle-left"></i></a>
<a href="#" @click="toggle(1)" class="carousel-btn next"><i class="iconfont icon-angle-right"></i></a>
//5个小点点
<div class="carousel-indicator">
// i是索引,sliders.length长度是5 就是循环5次显示 active是样式,加了样式就背景色变白,与index绑定 i-1是因为i是从1开始的,index与相差1,如果不-1 他达到最远的是sliders.length-1,小点点如果是5个,最远就是4个了,只能所以需要-1
<span v-for="i in sliders.length" :key="i" :class="{ active: index === i - 1 }"></span>
</div>
</div>
</template>
<script>
import { ref, watch, onMounted } from 'vue'
export default {
name: 'XtxCarousel',
props: {
sliders: {
type: Array,
default: () => []
},
duration: {
type: Number,
default: 2
},
autoplay: {
type: Boolean,
default: true
}
},
setup(props) {
console.log(props.sliders)
// 自动轮播的效果
const index = ref(0) index初识值为0模板可以显示第一张图片
let timer = null
const autoplayFn = () => {
clearInterval(timer)
// 2.自动轮播
timer = setInterval(() => {
index.value++
if (index.value >= props.sliders.length) {
index.value = 0
}
}, props.duration * 1000) // 设置为秒
}
watch(
() => props.sliders,
() => {
if (props.autoplay && props.sliders.length > 0) {
autoplayFn()
}
},
{
immediate: true
}
)
// 1.左右箭头点击显示上一页或者下一页
const toggle = step => {
index.value += step
// 点击右键
if (index.value >= props.sliders.length) {
index.value = 0
return
}
// 点击左键
if (index.value < 0) {
index.value = props.sliders.length - 1
}
}
// 3.进入就轮播图就停止,离开就继续轮播
const start = () => {
if (props.sliders.length > 0 && props.autoplay) {
autoplayFn()
}
}
const stop = () => {
clearInterval(timer)
}
// 最后销毁定时器,不然已经看不到轮播图了,一致都还在浪费资源
onMounted(() => {
clearInterval(timer)
})
return { index, toggle, start, stop }
}
}
</script>
<style scoped lang="less">
.xtx-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, 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>