视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
基于vue2.0实现简单轮播图
2020-11-27 22:25:03 责编:小采
文档

因为之前一直在忙公司的项目,vue这块就生疏了不少,正好借这个小demo复习下vue的知识。

先来个效果图:

如图所示,实现的就是一个间隔2.5s自动向左切换下一张的轮播图,同时鼠标移入停止轮播,移出回复轮播;
而下方按钮会根据当前图片自动变红且可以手动控制当前图片。

思路:

整个demo分为轮播图片和控制span两个部分。
按照前端工程化的需求来说,这两个部分应该解耦成两个component最后再导入页面比较合理,但由于demo较为简单,
作为练手就不搞那么复杂了,对项目有追求【强迫症】的童鞋可以往组件化的目标靠,具体方法参考我之前的博文。

第一步,先写出整体框架:

<template> 
 <div class="slide"> 
 <div class="slideshow"> 
 <ul> 
 <li v-for="(img, index) in imgArray" :key="index"> 
 <a href="#"> 
 <img :src='img'> 
 </a> 
 </li> 
 </ul> 
 </div> 
 <div class="bar"> 
 <span v-for="(item, index) in imgArray" :key="index"></span> 
 </div> 
 </div> 
</template> 

我们使用v-for列表渲染两个部分,值得注意的是列表渲染最好要提供一个key值,至于为什么官方文档说得很复杂,
就我所知的是如果不加key值在使用transition-group也就是过渡效果的时候会出现bug,官方给出的建议也是尽可能
在列表渲染的时候加上key值,百利无一害,养成习惯就好。

第二步:

在上一步我们渲染的是一个img数组,具体:

data () { 
 return { 
 imgArray: [ 
 '../static/timg1.jpg', 
 '../static/timg2.jpg', 
 '../static/timg3.jpg', 
 '../static/timg4.jpg' 
 ] 
 } 
 } 

然后实现轮播的原理就是创建一个变量与当前遍历的index值比对,若相同则显示,否则隐藏;
同时下方按钮index若也与变量相同则当前按钮变为活跃状态即背景变红。

<template> 
 <div class="slide"> 
 <div class="slideshow"> 
 <ul> 
 <li v-for="(img, index) in imgArray" v-show="index===mark" :key="index"> 
 <a href="#"> 
 <img :src='img'> 
 </a> 
 </li> 
 </ul> 
 </div> 
 <div class="bar"> 
 <span v-for="(item, index) in imgArray" :class="{ 'active':index===mark }" :key="index"></span> 
 </div> 
 </div> 
</template> 

第三步:

创建定时器,每隔2.5s给变量mark+1,挂载到钩子函数created:

export default { 
 data () { 
 return { 
 mark: 0, //比对图片索引的变量 
 imgArray: [ 
 '../static/timg1.jpg', 
 '../static/timg2.jpg', 
 '../static/timg3.jpg', 
 '../static/timg4.jpg' 
 ] 
 } 
 }, 
 methods: { 
 autoPlay () { 
 this.mark++; 
 if (this.mark === 4) { //当遍历到最后一张图片置零 
 this.mark = 0 
 } 
 }, 
 play () { 
 setInterval(this.autoPlay, 2500) 
 }, 
 change (i) { 
 this.mark = i 
 } 
 }, 
 created () { 
 this.play() 
 } 
} 
</script> 

第四步:

加上css文件,出现基本的效果。

<style> 
 * { 
 margin: 0; 
 padding: 0; 
 list-style: none; 
 } 
 .slide { 
 width: 1024px; 
 height: 320px; 
 margin: 0 auto; 
 margin-top: 50px; 
 overflow: hidden; 
 position: relative; 
 } 
 .slideshow { 
 width: 1024px; 
 height: 320px; 
 } 
 li { 
 position: absolute; 
 } 
 img { 
 width: 1024px; 
 height: 320px; 
 } 
 .bar { 
 position: absolute; 
 width: 100%; 
 bottom: 10px; 
 margin: 0 auto; 
 z-index: 10; 
 text-align: center; 
 } 
 .bar span { 
 width: 20px; 
 height: 5px; 
 border: 1px solid; 
 background: white; 
 display: inline-block; 
 margin-right: 10px; 
 } 
 .active { 
 background: red !important; 
 } 
</style> 

第五步:

现在我们得到的效果还是每隔一段时间图片突然变成另外一张,用户体验很差,达不到轮播的效果。
所以我们得加上过渡效果。
html:

<transition-group tag="ul" name="image"> 
 <li v-for="(img, index) in imgArray" v-show="index===mark" :key="index"> 
 <a href="#"> 
 <img :src='img'> 
 </a> 
 </li> 
</transition-group> 

css:

.image-enter-active { 
 transform: translateX(0); 
 transition: all 1.5s ease; 
 } 
 .image-leave-active { 
 transform: translateX(-100%); 
 transition: all 1.5s ease; 
 } 
 .image-enter { 
 transform: translateX(100%); 
 } 
 .image-leave { 
 transform: translateX(0); 
 } 

这里因为我们是给一个渲染列表加上过渡效果所以要使用transition-group而不是单元素的transition,否则会报错。
另外就是记得给transition-group加上tag="ul"属性,不然就会被默认渲染成span了。
css部分需要关联name属性值作为前缀。

第六步:

给下方按钮增加切换图片的点击事件。
最后我们再加上移入/移出实现关闭/打开定时器效果,即用户鼠标停留当前图片停止滚动,移出则继续。

<template> 
 <div class="slide" v-on:mouseover="stop()" v-on:mouseout="move()"> 
 <div class="slideshow"> 
 <transition-group tag="ul" name="image"> 
 <li v-for="(img, index) in imgArray" v-show="index===mark" :key="index"> 
 <a href="#"> 
 <img :src='img'> 
 </a> 
 </li> 
 </transition-group> 
 </div> 
 <div class="bullet"> 
 <span v-for="(item, index) in imgArray" :class="{ 'active':index===mark }" 
 @click="change(index)" :key="index"></span> 
 </div> 
 </div> 
</template> 
 
<script> 
export default { 
 data () { 
 return { 
 timer: null, //定时器 
 mark: 0, //比对图片索引的变量 
 imgArray: [ 
 '../static/timg1.jpg', 
 '../static/timg2.jpg', 
 '../static/timg3.jpg', 
 '../static/timg4.jpg' 
 ] 
 } 
 }, 
 methods: { 
 autoPlay () { 
 this.mark++; 
 if (this.mark === 4) { 
 this.mark = 0 
 } 
 }, 
 play () { 
 this.timer = setInterval(this.autoPlay, 2500) 
 }, 
 change (i) { 
 this.mark = i 
 }, 
 stop () { 
 clearInterval(this.timer) 
 }, 
 move () { 
 this.timer = setInterval(this.autoPlay, 2500) 
 } 
 }, 
 created () { 
 this.play() 
 } 
} 
</script> 

这个地方卡了我很长时间,因为根据原生js定时器的思路在定义定时器的时候就应该设置变量,然后把这个变量传到clearInterval函数里。
问题在于vue函数里设置变量很不可取,存在定义域的问题,开启定时器跟关闭定时器是两个函数,不能共用一个变量。
后来灵机一动,想到不如把变量写在data里面?
一试,成功!

至此,轮播图的功能基本实现。
当然,项目做的比较简陋也存在一些bug,如当一个切换动画未完成前点击另一个按钮会出现神奇的交错现象,由于时间关系还未解决,
希望各位看官能提出宝贵的建议!

下载本文
显示全文
专题