vue写一个轮播图效果

116 阅读1分钟

一、原理

在轮播图数组advertisements中,定义一个变量currentIndex = 0表示第一张图片,advertisements[currentIndex],然后获取每张图片的下标。点击切换图片时把当前图片的下标赋值给currentIndex即可实现图片切换显示。

二、定义变量

data() {
  return {
    advertisements: [],
    currentIndex: 0, //默认显示图片
    againClick: true, //禁止数据频繁切换
    timer:null,//定时器
  }
},

三、模板渲染

<template>
    <div>
    
      <div class="swiper relative" v-if="advertisements&&advertisements.length>0">
        <div class="item" v-if="advertisements[currentIndex]&&advertisements[currentIndex].thumb">
          <img class="curPer" :src="advertisements[currentIndex].thumb">
        </div>
        <div class="page" v-if="advertisements.length > 1">
          <ul class="flex-box">
            <li @click="gotoPage(prevIndex)">&lt;</li>
            <li v-for="(item,index) in advertisements" @click="gotoPage(index)" class="swiper-bullet box-b"
              :class="{'current active':currentIndex == index}">
            </li>
            <li @click="gotoPage(nextIndex)">&gt;</li>
          </ul>
        </div>
      </div>
    
    </div>
</template>

四、点击小圆点切换图片

<div class="page" v-if="advertisements.length > 1">
  <ul class="flex-box">
    <li v-for="(item,index) in advertisements" @click="gotoPage(index)" class="swiper-bullet box-b"
      :class="{'current active':currentIndex == index}">
    </li>
  </ul>
</div>

li标签里执行一个点击函数,把当前下标值传进来。点击时设置currentIndex的值为当前的下标值。

methods: {
  gotoPage(index) {
    this.currentIndex = index;
  }
}

五、左右按钮切换图片

<li @click="gotoPage(prevIndex)">&lt;</li>
<li v-for="(item,index) in advertisements" @click="gotoPage(index)" :class="{'current':currentIndex == index}">{{index+1}}</li>
<li @click="gotoPage(nextIndex)">&gt;</li>

定义两个变量作为参数prevIndex和nextIndex,利用计算属性算出当前图片的上一张图片或者下一张图片的下标(加1和减1操作)。

computed: {
  //上一张
  prevIndex() {
    if(this.currentIndex == 0) {
      return this.advertisements.length - 1;
    }else{
      return this.currentIndex - 1;
    }
  },
  //下一张
  nextIndex() {
    if(this.currentIndex == this.advertisements.length - 1) {
      return 0;
    }else {
      return this.currentIndex + 1;
    }
  }
}

六、定时器切换图片

定义一个定时器,每X秒执行一次nextIndex()函数即可。

//定时器
runInv() {
  this.timer = setInterval(() => {
    this.gotoPage(this.nextIndex)
  }, 1000)
}

七、css样式

<style>
.swiper {
  min-height: 300px;
  min-width: 1200px;
  margin-left: auto;
  margin-right: auto;
  position: relative;
  overflow: hidden;
  z-index: 1;
  // height: 438px;

  img {
    width: 100%;
    display: block;
  }

  .page {
    // background: rgba(0, 0, 0, .5);
    position: absolute;
    text-align: center;
    transition: .3s;
    transform: translateZ(0);
    z-index: 10;
    bottom: 25px;
    left: 0;
    width: 100%;

    ul {
      width: 100%;
    }

    .swiper-bullet {
      background: #fff;
      border-radius: 0;
      width: 56px;
      height: 3px;
      margin: 0 5px;
      cursor: pointer;
      opacity: 0.6;
      border: 2px solid #fff;
    }

    .active {
      opacity: 1;
    }
  }

  .page ul {
    float: right;
  }

  .current {
    color: #ff6700;
  }


  .item {
    position: relative;
    width: 100%;
    height: 100%;
    z-index: 1;
    display: -ms-flexbox;
    display: flex;
    transition-property: transform;
    box-sizing: content-box;
    max-height: 540px;
  }
}
</style> 

八、完整例子

<template>
    <div>
    
      <div class="swiper relative" v-if="advertisements&&advertisements.length>0">
        <div class="item" v-if="advertisements[currentIndex]&&advertisements[currentIndex].thumb">
          <img class="curPer" :src="advertisements[currentIndex].thumb">
        </div>
        <div class="page" v-if="advertisements.length > 1">
          <ul class="flex-box">
            <li @click="gotoPage(prevIndex)">&lt;</li>
            <li v-for="(item,index) in advertisements" @click="gotoPage(index)" class="swiper-bullet box-b"
              :class="{'current active':currentIndex == index}">
            </li>
            <li @click="gotoPage(nextIndex)">&gt;</li>
          </ul>
        </div>
      </div>
    
    </div>
</template>

<script>
export default {
    data() {
      return {
        advertisements: [],
        currentIndex: 0, //默认显示图片
        againClick: true, //禁止数据频繁切换
        timer:null,
      }
    },
     computed: {
     //上一张
      prevIndex() {
        if(this.currentIndex == 0) {
          return this.advertisements.length - 1;
        }else{
          return this.currentIndex - 1;
        }
      },
      //下一张
      nextIndex() {
        if (this.currentIndex == this.advertisements.length - 1) {
          return 0;
        } else {
          return this.currentIndex + 1;
        }
      },
    }
    created() {
      //模拟轮播
      that.runInv();
    },
    methods: {
        //定时器
        runInv() {
            let that = this;
            that.setTimer();
            // 通过$once来监听定时器,在beforeDestroy钩子可以被清除。
            that.$once('hook:beforeDestroy', () => {
              clearInterval(that.timer);
            })
        },
        setTimer(){
            let that = this;
            that.timer = setInterval(() => {
              that.gotoPage(that.nextIndex)
            }, 4000)
        },
        gotoPage(index) {
            let that = this;
            if (index == that.currentIndex) return;
            if (!that.againClick) return;
            that.againClick = false;
            that.currentIndex = index;
            clearInterval(that.timer);
            that.setTimer();
            that.againClick = true;
      },
    }
}
</script>

<style>
.swiper {
  min-height: 300px;
  min-width: 1200px;
  margin-left: auto;
  margin-right: auto;
  position: relative;
  overflow: hidden;
  z-index: 1;
  // height: 438px;

  img {
    width: 100%;
    display: block;
  }

  .page {
    // background: rgba(0, 0, 0, .5);
    position: absolute;
    text-align: center;
    transition: .3s;
    transform: translateZ(0);
    z-index: 10;
    bottom: 25px;
    left: 0;
    width: 100%;

    ul {
      width: 100%;
    }

    .swiper-bullet {
      background: #fff;
      border-radius: 0;
      width: 56px;
      height: 3px;
      margin: 0 5px;
      cursor: pointer;
      opacity: 0.6;
      border: 2px solid #fff;
    }

    .active {
      opacity: 1;
    }
  }

  .page ul {
    float: right;
  }

  .current {
    color: #ff6700;
  }


  .item {
    position: relative;
    width: 100%;
    height: 100%;
    z-index: 1;
    display: -ms-flexbox;
    display: flex;
    transition-property: transform;
    box-sizing: content-box;
    max-height: 540px;
  }
}
</style>