轮播图模块(vue)
通过属性方式传值
值为一个数组、每一项含有imgUrl(图片地址)、link(跳转链接),link为可选属性
<template> <div class="createBannerArea"> <!-- 图片区域 --> <div class="imgArea" ref="imgArea" style="marginLeft:0" @mouseenter="onMouseenter" @mouseleave="onMouseleave"> <template v-if="arrUrl[0].link"> <a v-for="(item,index) in arrUrl" :key="index" href="item.link"> <img :src=item.imgUrl :alt="item.imgUrl" srcset=""> </a> <a href="arrUrl[0].link"> <img :src=arrUrl[0].imgUrl alt="" srcset=""> </a> </template> <template v-else> <img v-for="(item,index) in arrUrl" :key="index" :src=item.imgUrl alt="" srcset=""> <img src=arrUrl[0].imgUrl alt="" srcset=""> </template> </div> <!-- 小圆圈 --> <div class="circleArea"> <span ref="circle" v-for="(item,index) in arrUrl" :key="index" @click="onClick(index)"></span> </div> </div> </template> <script> export default { name: 'createBannerArea', data(){ return { timer1: null, // 图片切换定时器 timer2: null, // 图片过渡定时器 time1: 2000, // timer1定时器的时间 time2: 10, // timer2定时器的时间 time3: 500, // 多久完成过渡 index: 0, // 当前显示第几张 circleColor: '#ddd', // 圆圈颜色 activeCirclecolor: '#aaa', // 选中状态时圆圈颜色 } }, props: { arrUrl: { type: Array, default: function(){ return [] } } }, methods: { onMouseenter(){ clearInterval(this.timer1) this.timer1 = null }, onMouseleave(){ this.autoChange() }, onClick(index){ this.index = index this.setStatus(); this.autoChange(); }, // 轮播 autoChange(){ if(this.timer1){ clearInterval(this.timer1); this.timer1 = null } this.timer1 = setInterval(() => { if(this.index == this.arrUrl.length){ this.index = 1; }else{ this.index ++ } this.setStatus() }, this.time1); }, // 设置动画 setStatus(){ for(var i = 0; i < this.arrUrl.length; i++){ if(i == this.index){ this.$refs.circle[i].style.backgroundColor = this.activeCirclecolor; }else{ this.$refs.circle[i].style.backgroundColor = this.circleColor; } if(this.index === this.arrUrl.length){ this.$refs.circle[0].style.backgroundColor = this.activeCirclecolor; } } var start = parseInt(this.$refs.imgArea.style.marginLeft); var end = -this.index * 100; var dis = end - start; var speed = dis / this.time3; if(this.timer2){ clearInterval(this.timer2); this.timer2 = null } this.timer2 = setInterval(() => { start += speed * this.time2; this.$refs.imgArea.style.marginLeft = start + '%'; if(Math.abs(end - start) < 1){ if(this.index == this.arrUrl.length){ this.$refs.imgArea.style.marginLeft = 0 + '%'; }else{ this.$refs.imgArea.style.marginLeft = end + '%'; } clearInterval(this.timer2); this.timer2 = null } }, this.time2); }, // 清除定时器 clearTimer(){ clearInterval(this.timer1); clearInterval(this.timer2); }, onVisibilitychange(){ document.addEventListener("visibilitychange", this.isDocuHidden) }, // 判断页面是hidden还是visible状态,目的是当最小化和切换其他标签页时,停止定时器,优化性能 // visible: 页面内容至少是部分可见。 在实际中,这意味着页面是非最小化窗口的前景选项卡。 // hidden: 页面内容对用户不可见。 在实际中,这意味着文档可以是一个后台标签,或是最小化窗口的一部分,或是在操作系统锁屏激活的状态下。 isDocuHidden(){ if(document.visibilityState == 'hidden'){ this.clearTimer() }else if(document.visibilityState == 'visible'){ this.autoChange(); } } }, beforeDestroy(){ // 当组件销毁前清除定时器和document的事件 this.clearTimer() document.removeEventListener('visibilitychange',this.isDocuHidden) }, mounted: function () { this.$nextTick( () => { this.autoChange() this.onVisibilitychange(); }) } } </script> <style scoped> .createBannerArea{ 100%; height: 500px; overflow: hidden; outline: 1px solid red; margin: 10px auto; } .createBannerArea .imgArea{ display: flex; flex-wrap: nowrap; 100%; height: 100%; } .createBannerArea .imgArea a{ flex: 0 0 auto; 100%; height: 100%; } .createBannerArea .imgArea img{ 100%; height: 100%; } .circleArea{ margin-top: -25px; text-align: center; } .circleArea span{ display: inline-block; 10px; height: 10px; margin: 0 10px; border-radius: 50%; background-color: #999; cursor: pointer; } .circleArea span:first-child{ background-color: #777; } </style>