用better-scroll做的轮播图,为什么不能无缝循环?

一.实锤:
1.1 html:

  <div class="slider" ref="slider">
    <div class="slider-group" ref="sliderGroup">
      <div v-for="item in recommends">
        <a :href="item.linkUrl">
          <img class="needsclick" @load="loadImage" :src="item.picUrl">
        </a>
    </div>
    <div class="dots">
      <span class="dot" :class="{active: currentPageIndex === index }" v-for="(item, index) in dots"></span>
    </div>
  </div>

1.2 script:


<script>
import BScroll from 'better-scroll'
import {addClass} from 'common/js/dom'
export default{
  props: {
    loop: {
      type: Boolean,
      default: true
    },
    autoPlay: {
      type: Boolean,
      default: true
    },
    interval: {
      type: Number,
      default: 4000
    }
  },
  data() {
    return {
      dots: [],
      currentPageIndex: 0
    }
  },
  mounted() {
    setTimeout(() => {
      this._setSliderWidth()
      this._initSlider()
      this._initDots()

      if (this.autoPlay) {
        this._play()
      }
    }, 20)

    window.addEventListener('resize', () => {
      if (!this.slider) {
        return
      }
      this._setSliderWidth(true)
      this.slider.refresh()
    })
  },
  methods: {
    _setSliderWidth(isResize) {
      // 取轮播组的子元素
      this.children = this.$refs.sliderGroup.children

      let width = 0
      // 取轮播组件宽度(即屏幕宽度)
      let sliderWidth = this.$refs.slider.clientWidth
      for (var i = 0; i < this.children.length; i++) {
        let child = this.children[i]
        addClass(child, 'slider-item')

        // 设置轮播子图宽度为屏幕宽度
        child.style.width = sliderWidth + 'px'
        // 将轮播子图累加
        width += sliderWidth
      }

      // ???
      if (this.loop && !isResize) {
        width += 2 * sliderWidth
      }
      this.$refs.sliderGroup.style.width = width + 'px'
    },
    _initSlider() {
      this.slider = new BScroll(this.$refs.slider, {
        scrollX: true,
        scrollY: false,
        momentum: false,
        snap: true,
        snapLoop: this.loop, // 循环
        snapThreshold: 0.3,
        snapSpeed: 400,
        click: true
      })

      this.slider.on('scrollEnd', () => {
        let pageIndex = this.slider.getCurrentPage().pageX
        if (this.loop) {
          pageIndex -= 1
        }
        this.currentPageIndex = pageIndex

        if (this.autoPlay) {
          clearTimeout(this.timer)
          this._play()
        }
      })
    },
    _initDots() {
      this.dots = new Array(this.children.length)
    },
    _play() {
      let pageIndex = this.currentPageIndex + 1
      if (this.loop) {
        pageIndex += 1
      }
      this.timer = setTimeout(() => {
        this.slider.goToPage(pageIndex, 0, 400)
      }, this.interval)
    }
  }
}
</script>

二.线索:

  1. 可以轮播,但不能循环(不能从第一张往前翻,不能从最后一张往后翻)
  2. 按教程里给slider-group增加了2个slider的宽度(是为无缝循环准备的?),但他们出现在轮播图片的末尾(2个空白)
  3. 第一张图没有对应dot,第二张图对应第一个dot,以此类推
  4. 对比了教程里的代码,几乎没有区别,数据来源也是一样,替换了代码也是这样的表现,so百思不得其解

完整代码:github

找到原因了,是版本的问题,在0.1.15版本这么写是没问题的,snap的各个配置项并列写,但在新版本要写在一个snap对象内,就像采纳的答案写的那样,另外还有几个小修改,不知是个人原因还是版本差异,总之先贴出来给大家参考吧
`

  1. 降版本后dots会多两个:
    _initDots() {
      // this.dots = new Array(this.children.length) // 原写法
      this.dots = new Array(this.children.length - 2)
    },

2.升版本,修改创建better-scroll的配置时,dot与图片不对应:

  // bs对象配置方法中(配置后):
  this.slider.on('scrollEnd', () => {
        let pageIndex = this.slider.getCurrentPage().pageX
        // 老版本有,新版去掉:
        // if (this.loop) {
        //   pageIndex -= 1
        // }
        this.currentPageIndex = pageIndex

        if (this.autoPlay) {
          clearTimeout(this.timer)
          this._play()
        }
      })
阅读 6.3k
4 个回答

新版本已经更新了,我也是找了好久

_initSlider() {

let slider = new BScroll(this.slider, {
  click: true,
  scrollX: true,
  scrollY: false,
  momentum: false,
  snap: {
    loop: true,
    threshold: 0.3,
    speed: 400
  },
})

这么写就可以了

better-scroll的版本从0.1.15已经到1.x的版本了,把源码的BS更新到最新版本也是这个情况,但..我也是才发现的不知道怎么解决

新手上路,请多包涵

我也刚刚遇到这个情况,请问这个你找到答案了吗?

承上莫_小语的答案。

_initDots() {
      this.dots = new Array(this.children.length)
    },
    // 初始化
    _initSlider() {
      this.slider = new BScroll(this.$refs.slider, {
        scrollX: true, // 左右滑动
        scrollY: false, // 禁止上下滑动
        momentum: false, // 惯性
        click: true,
        snap: {
          loop: true,
          threshold: 0.3,
          // snapLoop: this.loop, // 循环
          speed: 400
        }
      })

      this.slider.on('scrollEnd', () => {
        const pageIndex = this.slider.getCurrentPage().pageX

        this.currentPageIndex = pageIndex

        if (this.autoPlay) {
          clearTimeout(this.timer)
          this._play()
        }
      })
    },
    _play() {
      // const pageIndex = this.currentPageIndex + 1
      this.timer = setTimeout(() => {
        // this.slider.goToPage(pageIndex, 0, 400)
        this.slider.next()
      }, this.interval)
    }
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题