Vue.jsVue.js专区让前端飞

【四】轮播图组件

2020-02-25  本文已影响0人  大海爱奔跑

关于专题【vue开发音乐App】

轮播图属于基础组件,所以归纳到src/base/slide里面,新建slide.vue

一、html部分

<template>
  <div class="slider" ref="slider">
    <div class="slider-group" ref="sliderGroup">
      <slot>
      </slot>
    </div>
    <div class="dots">
      <span class="dot" v-for="(item, i) in dots" :key="i" :class="{active : currIndex === i}"></span>
    </div>
  </div>
</template>

二、js部分

js代码100余行,全部展开不利于浏览,所以先看整体结构:

<script type="text/ecmascript-6">
  import BScroll from 'better-scroll'
  import {addClass} from 'common/js/dom'

  export default {
    name: 'slider',
    props: {...},
    data () {...},
    mounted () {...},
    methods: {...},
    destoryed () {...}
  }
</script>
props
props: {
  loop: {
    type: Boolean,
    default: true
  },
  autoPlay: {
    type: Boolean,
    default: true
  },
  interval: {
    type: Number,
    default: 4000
  }
},
data
data () {
  return {
    dots: [],
    currIndex: 0
  }
},
mounted
mounted () {
  setTimeout(() => {
    this._setSliderWidth()
    this._initDots()
    this._initSlider()
    if (this.autoPlay) {
      this._play()
    }
  }, 20) // 浏览器刷新一般需要17毫秒

  window.addEventListener('resize', () => {
    if (!this.slider) {
      return false
    }
    this._setSliderWidth(true)
    this.slider.refresh()
  })
},
methods
methods: {
  _setSliderWidth (isResize) {...},
  _initDots () {...},
  _initSlider () {...},
  _play () {...}
}
_setSliderWidth()
// 获取轮播图宽度
_setSliderWidth (isResize) {
  this.children = this.$refs.sliderGroup.children

  let width = 0
  let sliderWidth = this.$refs.slider.clientWidth
  for (let i = 0; i < this.children.length; i++) {
    let child = this.children[i]
    addClass(child, 'slider-item')

    child.style.width = sliderWidth + 'px'
    width += sliderWidth
  }
  // 如果是循环播放,一头一尾需要多放一个dom
  if (this.loop && !isResize) {
    width += 2 * sliderWidth
  }
  this.$refs.sliderGroup.style.width = width + 'px'
},
_initDots()
// 初始化小圆点
_initDots () {
  this.dots = new Array(this.children.length)
},
_initSlider()
// 初始化轮播图
_initSlider () {
  this.slider = new BScroll(this.$refs.slider, {
    scrollX: true,
    scrollY: true,
    momentum: false, // 惯性
    snap: true,
    snapLoop: this.loop,
    snapThreshold: 0.3,
    snapSpeed: 400
  })
  this.slider.on('scrollEnd', () => {
    let pageIndex = this.slider.getCurrentPage().pageX
    if (this.loop) {
      pageIndex -= 1
    }
    this.currIndex = pageIndex

    if (this.autoPlay) {
      clearTimeout(this.timer)
      this._play()
    }
  })
},
_play()
// 播放
_play () {
  let index = this.currIndex + 1
  if (this.loop) {
    index += 1
  }
  this.timer = setTimeout(() => {
    this.slider.goToPage(index, 0, 400)
  }, this.interval)
}
destoryed
destoryed () {
  clearTimeout(this.timer)
}

三、css部分

<style lang="stylus" rel="stylesheet/stylus">
  // variable.styl传送门:https://wy310.cn/2020/01/11/vue-build-basic-style-structure/
  @import "~common/stylus/variable"

  .slider
    min-height: 1px
    .slider-group
      position: relative
      overflow: hidden
      white-space: nowrap
      .slider-item
        float: left
        box-sizing: border-box
        overflow: hidden
        text-align: center
        a
          display: block
          width: 100%
          overflow: hidden
          text-decoration: none
        img
          display: block
          width: 100%
    .dots
      position: absolute
      right: 0
      left: 0
      bottom: 12px
      text-align: center
      font-size: 0
      .dot
        display: inline-block
        margin: 0 4px
        width: 8px
        height: 8px
        border-radius: 50%
        background: $color-text-l
        &.active
          width: 20px
          border-radius: 5px
          background: $color-text-ll
</style>
上一篇下一篇

猜你喜欢

热点阅读