Vue项目中使用better-scroll实现一个轮播图

前言

better-scroll是一个很是很是强大的第三方库 在移动端利用这个库 不只能够实现一个很是相似原生ScrollView的效果 也能够实现一个轮播图的效果 这里就先记录一下本身实现这个效果的一些过程吧vue

思路

1.首先要肯定本身的HTML结构 基本结构就是一个wrapper包含一个content数组

2.其次须要明白的一个页面能够滚动的原理在于 当内容的高度超出了容器的高度才能够实现滚动 若是没有超出 那么就没有滚动的必要 所以第一点须要实现的就是 获取到全部内容的高度 因为实现的是一个轮播图 因此其实整个页面应该想象成这样 浏览器

滚动原理

这里能够很清楚的看到 当页面的横向宽度超出了视口的宽度 所以也就能够实现滚动 综上所述 能够看出 实现横向轮播最重要的一点在于宽度 所以 咱们首先要得到的就是整个轮播图的宽度bash

3.既然是个轮播图 那么用户同时也须要知道的就是 当前播放的是第几张图 也就是常见的"小白点" 小白点的个数用于告诉用户总共有几张图 而当前播放第几张图则能够在小白点上加上一些特殊样式的方法来告知用户app

4.轮播图也须要一些常见的属性 例如 页面渲染之后自动播放以及播放间隔 还有一个就是 是否支持循环轮播dom

快乐coding

理清思路之后 就能够开始干活了 1.完善HTML结构 其实代码很是简单 也就是建立两个div 而且添加ref引用能够方便的经过ref属性获取上下文ide

<div class="slider"
       ref="slider">
    <div class="slider-content"
         ref="sliderContent">
      <slot></slot>
    </div>
</div>
复制代码

这里用了vue中很是常见的slot插槽 为的是当咱们在外部调用这个slider组件的时候 能够方便的在外部传入一些子组件函数

2.上文已经提到了一些控制slider的属性 因此须要在组件的props里接受这些属性 便于咱们在外部方便的控制这些属性oop

props: {
    // 是否循环播放
    loop: {
      type: Boolean,
      default: true
    },
    // 是否自动播放
    autoPlay: {
      type: Boolean,
      default: true
    },
    // 播放间隔
    interval: {
      type: Number,
      default: 3000
    }
  }
复制代码

3.一些初始步骤的完成的差很少了之后 咱们须要借助到vue的一个生命周期钩子 mounted 也就是当页面渲染完毕之后 去获取轮播图的宽度以及初始化轮播图的一些设置动画

mounted: function () {
   setTimeout(() => {
      this.setSliderWidth()
     this.initSlider()
   }, 20)
复制代码

这里有一个小小的tips 就是 一般状况下 浏览器渲染dom的时间为17ms 因此这里使用了一个延迟函数 在20ms之后去调用这些方法 也就是确保浏览器的dom被正确渲染 防止出现一些问题

4.上面只是调用了这个方法 尚未实现这些方法 首先在设置宽度的方法里 咱们须要经过$refs.sliderContent拿到上下文 而且经过一个$refs.slider.clientWidth方法拿到当前屏幕宽度 而后遍历这个容器 取得容器里的全部内容 同时把获取的内容宽度设置为这个屏幕的宽度 最后将全部的内容的宽度相加 就能够获得整个slider的宽度 说了这么多 感受很绕口 因此仍是看下代码吧

// 设置slider的宽度
    setSliderWidth: function (isResize) {
      // 获取slider里的全部的子元素
      this.children = this.$refs.sliderContent.children
      // console.log(this.children)
      // 计算宽度  = 图片个数+每张图片的宽度
      let width = 0
      // 获取手机屏幕的宽度
      let sliderWidth = this.$refs.slider.clientWidth
      
      for (let i = 0; i < this.children.length; i++) {
        // 获取children里的每一项内容 
        let child = this.children[i]
   
        child.style.width = sliderWidth + 'px'
        width += sliderWidth
      }
      if (this.loop) {
        width += 2 * sliderWidth
      }
      this.$refs.sliderContent.style.width = width + 'px'
    }
复制代码

这样咱们就获取了整个slider的宽度 还有一个细节在于 当若是是loop的时候 better-scroll会在头尾克隆两份 因此宽度会须要*2 接下去就是实现一些初始化better-scroll的一些配置了 具体的参数内容能够从better-scorll官网上查询到 这里就很少作赘述了

// 设置宽度之后初始化slider
    initSlider: function () {
      this.slider = new BScroll(this.$refs.slider, {
        scrollX: true,
        scrollY: false,
        momentum: false,
        snap: {
          loop: this.loop,
          threshold: 0.3,
          speed: 400
        },
        click: true
      })
    }
复制代码

5.实现上述两个方法之后 其实轮播图基本已经能够在页面上看到了 大概就是长成这样 不过这样写完之后 会发现轮播图是没有办法自动轮播的以及当前显示的是几张图的样式并无正确显示 因此接下去就是实现这两个方法 ps:这里的图片数据来源什么 是请求了QQ音乐banner的接口文件

轮播图的效果

6.实现dots样式的正确加载 这里用到了vue中样式的绑定

<div class="dots">
      <span class="dot"
            v-for="(item, index) of dots"
            :class="{active:currentPageIndex === index}"
            :key="index">
      </span>
    </div>
复制代码

也就是说 咱们经过下标来绑定样式 同时监听一个better-scroll的'scrollEnd'事件 当滚动结束的时候调用getCurrentPage()这个方法 这个方法会有一个返回值pageX 也就是横向滚动到第几页 把这个返回值赋值给currentPageIndex 从而达到正确显示样式的目的

this.slider.on('scrollEnd', () => {
        let page = this.slider.getCurrentPage().pageX
        this.currentPageIndex = page
        // 当滚动结束之后 若是是自动播放的话 那么首先要清除定时器(防止手动拖动轮播图之后图片没法正确显示)而后再次执行方法 才能实现轮播
        if (this.autoPlay) {
          clearTimeout(this.timer)
          this.play()
        }
      })
复制代码

7.实现自动播放功能 better-scroll也提供了一个接口goToPage(x, y, time, easing) 顾名思义也就是转到对应页面 其中几个参数分别表明 x表示横向页面 y表示纵向页面 time表示动画执行时间 easing通常不建议修改 有了这个接口 其实就很是轻松了 咱们只须要在methods里再写一个Play方法 具体的思路就是 经过currentPageIndex+=1获得下一张要播放的图片的索引 同时当索引值达到图片数组的长度的时候将要索引从新赋值为0就行了 并在页面渲染了之后调用就能够了

play: function () {
      let playPage = this.currentPageIndex + 1
      if (playPage === this.children.length - 2) {
        playPage = 0
      }
      setTimeout(() => {
        this.slider.goToPage(playPage, 0, 400)
      }, this.interval)
    }
复制代码

这里也有个细节就是 当设置这个轮播图为循环滚动的时候 better-scroll会自动在头尾各克隆一份图片 因此长度须要减去2 这样就能够实现轮播图的自动播放了

###总结 到这里就成功经过better-scroll实现了一个轮播图的实现 具体的过程其实不算多难 主要就是理清思路 就好啦!冲鸭!