轮播图模块(vue)

轮播图模块(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>
原文地址:https://www.cnblogs.com/wangjie-nf/p/11536520.html