1. 程式人生 > >前端框架Vue(14)—— 利用 vue 過渡效果(transition)+定時器 實現輪播圖通用元件

前端框架Vue(14)—— 利用 vue 過渡效果(transition)+定時器 實現輪播圖通用元件

序論:

    輪播圖 相信都不會陌生,很多的網站都會有,而且實現的方式也是千變萬化,可以利用封裝好的 UI 庫 (bootstrap),

也可以原生的 JS 進行編寫。但是其中,動畫(transition)和定時器都是必不可少的。本文就是利用 vue 自帶的 

transition 動畫過渡效果加上定時器編寫輪播圖。

效果:

這裡寫圖片描述


1、功能分析。

從上面的效果圖中看,有四個基本功能:

1、自動的輪播的功能;
2、點選左右箭頭(pre、next)進行的切換;
3、點選數字切換到對應的圖片的功能。
4、滑鼠懸停、移出控制輪播圖的停、啟。

2、場景介紹、分析。

環境是 vue 元件的形式,輪播圖模組是以元件的形式,內嵌在父元件中。這樣的好處是輪播圖功能,低耦合,複用性高,即插即用。這邊我將輪播圖的元件取名為 Carousel.vue,父元件為 app.vue。

這裡寫圖片描述


3、原始碼分析。

1、父元件 app.vue。

<template>
    <div id="WBAQPage" class="WBAQPage">
        <carousel :slides="slides" :inv="invTime"></carousel>
    </div>
</template>
<script>
import carousel from '../../components/Carousel.vue'
    export default {
        data () {
            return
{ invTime: 2000, slides: [ { src:require('../../assets/pic1.jpg'), title:'xxx1', }, { src:require('../../assets/pic2.jpg'), title:'xxx2'
}, { src:require('../../assets/pic3.jpg'), title:'xxx3' }, { src:require('../../assets/pic4.jpg'), title:'xxx4' } ] } }, components: { carousel } }
</script> <style scoped></style>

父元件中主要有三件事:

1、import 引入子元件進行顯示。
2、將歸納輪播圖屬性的陣列 slides 傳給子元件。
3、將輪播間隔的時間引數 invTime 傳給子元件。

2、子元件 Carousel.vue

<template>
  <div class="slide-show" @mouseover="clear" @mouseout="run">
    <div class="slide-img">
      <a>
        <transition name="slide-trans">
          <img v-if="isShow" :src="slides[nowIndex].src">
        </transition>
        <transition name="slide-trans-old">
          <img v-if="!isShow" :src="slides[nowIndex].src">
        </transition>
      </a>
    </div>
    <h2>{{ slides[nowIndex].title }}</h2>
    <ul class="slide-pages">
      <li @click="goto(prevIndex)">&lt;</li>
      <li v-for="(item, index) in slides" @click="goto(index)">
        <a :class="{on: index === nowIndex}">{{ index + 1 }}</a>
      </li>
      <li @click="goto(nextIndex)">&gt;</li>
    </ul>
  </div>
</template>

<script>
export default {
  props: {
    slides: {
      type: Array,
      default: []
    },
    inv: {
      type: Number,
      default: 1000
    }
  },
  data () {
    return {
      nowIndex: 0,
      isShow: true
    }
  },
  computed: {
    prevIndex () {
      if (this.nowIndex === 0) {
        return this.slides.length - 1
      }
      else {
        return this.nowIndex - 1
      } 
    },
    nextIndex () {
      if (this.nowIndex === this.slides.length - 1) {
        return 0
      }
      else {
        return this.nowIndex + 1
      }
    }
  },
  methods: {
    goto (index) {
      this.isShow = false
      setTimeout(() => {
        this.isShow = true
        this.nowIndex = index
      }, 10)
    },
    run () {
      this.invId = setInterval(() => {
        this.goto(this.nextIndex)
      }, this.inv)
    },
    clear () {
      clearInterval(this.invId)
    }
  },
  mounted () {
    this.run();
  }
}
</script>

<style scoped>
.slide-trans-enter-active {
  transition: all .5s;
}
.slide-trans-enter {
  transform: translateX(900px);
}
.slide-trans-old-leave-active {
  transition: all .5s;
  transform: translateX(-900px);
}
.slide-show {
  position: relative;
  margin: 15px 15px 15px 0;
  width: 900px;
  height: 500px;
  overflow: hidden;
}
.slide-show h2 {
  position: absolute;
  width: 100%;
  height: 100%;
  color: #fff;
  background: #000;
  opacity: .5;
  bottom: 0;
  height: 30px;
  text-align: left;
  padding-left: 15px;
}
.slide-img {
  width: 100%;
}
.slide-img img {
  width: 100%;
  position: absolute;
  top: 0;
  left: 0;
}
.slide-pages {
  position: absolute;
  bottom: 10px;
  right: 15px;
}
.slide-pages li {
  display: inline-block;
  padding: 0 10px;
  cursor: pointer;
  color: #fff;
}
.slide-pages li .on {
  text-decoration: underline;
}
</style>

接下來,我會對上面提到的四個功能對應的方法,進行簡單的分析:

1、圖片的切換(pre、next),實現輪播。

原理:利用切換 img 中的 src 來達到圖片的切換,在之前的父元件中,我們已經對四張圖片的屬性,進行了陣列封裝, 那麼我們只需要不斷改變陣列的下標就能達到目的。如 img 中 :src="slides[0].src" , 那麼顯示的就是第一張圖片。這樣我們就可以抽象出一個 nowIndex 的變數當做是當前圖片的下表,這樣我們只需要去控制 nowIndex 就能切換。用到的是 goto(index) 的方法。

goto (index) {
        this.nowIndex = index
    },

首先定義 nowIndex 為 0,所以初始化的時候,顯示的是第一張圖片。當我點選 pre 的時候,

prevIndex () {
      if (this.nowIndex === 0) {
        return this.slides.length - 1
      }
      else {
        return this.nowIndex - 1
      } 
    },

如果 nowIndex 為 0,那麼現在應該顯示的最後一張圖片。程式碼中 this.slides.length - 1 ,不然就是 減1. 上一張圖片。點選 next 同理:

nextIndex () {
      if (this.nowIndex === this.slides.length - 1) {
        return 0
      }
      else {
        return this.nowIndex + 1
      }
    }

這邊的一大坑點是,你需要將這兩個方法寫在 計算屬性computed 中會比較的優雅,這樣一旦 nowIndex 改變,就會觸發這兩個事件,返回對應的值。

2、點選數字切換到對應的圖片。

這個的原理和 pre、next 一致,且更加的簡單,因為他不需要進行計算,切換的方法只有一個,就是 goto( index ), 所以這邊你只需要對每個數字繫結 goto(index)的 click 方法。

3、自動輪播功能。

自動輪播,需要用到的就是定時器,即每隔一個時間就呼叫一次 goto(index):

run () {
      this.invId = setInterval(() => {
        this.goto(this.nextIndex)
      }, this.inv)
    },

這邊寫了一個 run 的方法,每隔 inv 的時間,就去傳入 nextIndex 。這樣就可以自動的進行圖片切換。

4、滑鼠懸停、移出時進行輪播控制。

@mouseover="clear" @mouseout="run"

當滑鼠移出的時候,可以輪播,那就呼叫 run;如果滑鼠移入,停止輪播,那就清除定時器,clear。

clear () {
      clearInterval(this.invId)
    }

4、vue 動畫過渡效果

vue 中 transition 可以利用 v-show 和 v-if 進行觸發,我這邊利用的是 v-if 的顯示隱藏觸發動畫。

<transition name="slide-trans">//新的圖片進入
          <img v-if="isShow" :src="slides[nowIndex].src">
</transition>

<transition name="slide-trans-old">//舊的圖片移出
          <img v-if="!isShow" :src="slides[nowIndex].src">
</transition>

這邊在配合 CSS 中的 transform 平移,實現切換動畫:

.slide-trans-enter-active {
  transition: all .5s;
}
.slide-trans-enter {
  transform: translateX(900px);//大小需要和 show-img 外框的大小一致
}
.slide-trans-old-leave-active {
  transition: all .5s;
  transform: translateX(-900px);//大小需要和 show-img 外框的大小一致
}

上面的兩個元件的程式碼可以直接使用,輪播 carousel 元件是獨立的,可擴充套件的,可複用在任何的 vue 專案中。你只需要將圖片的屬性進行自定義,就可以有自己的輪播圖了。