轮播组件——基于原生 && Vue

基于 better-scroll 的轮播图组件

在做移动端轮播图的时候,本想沿用之前 PC 端的轮播图,后来发现并没有支持 touch 事件,所以采用了 better-scroll 来实现轮播图组件。

关于 better-scroll 的介绍可以看官方文档 传送门

正如 文档中所说,学习 bette-scroll 的相关组件 最好的方式就是去看 example 目录下的 demo,我现在要实现轮播图组件,直接找到轮播图的 demo 代码部分 源码传送门

轮播组件——基于原生 && Vue_第1张图片
image.png

首先实现轮播图的基本思路是通过 width 设置 overflow: hidden 来达到目的,通过 translate 移动图片实现轮播,这里 translate 的事情 better-scroll 已经替我们干了

首先看下轮播图的 html 结构:

// 通过 slot 父组件传入图片等自定义内容

css 结构采用的是 stylus:

.slide 
    min-height: 1px
    .slide-group
      position: relative
      overflow: hidden
      white-space: nowrap
      .slide-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
      transform: translateZ(1px)
      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

好了,下面我们看看如何组织下代码,首先我们需要看一下 better-scroll 的文档,就会知道 better-scroll 执行的时机是 dom 结构渲染完毕后,所以最好的执行时机可以通过 this.$nextTick() 去实现,当然也可以通过定时器 setTimeout(fn, 20) 这样一个经验值去实现也是没有问题的。

确定好了执行时机,我们开始初始化相关内容,比如轮播容器宽度以及 better-scroll 等

初始化 slide 宽度

// 获取图片的 clientWidth
// 当需要循环播放的时候在首尾添加两个图片的 clientWidth,做一个过渡
// 给整个 slideGroup 设置 width

_setSliderWidth(isResize) {
    this.children = this.$refs.slideGroup.children 
    let width = 0 
    let slideWidth = this.$refs.slide.clientWidth
    for (let i = 0; i < this.children.length; i++) {
        let child = this.children[i] 
        addClass(child, 'slide-item') 
        child.style.width = slideWidth + 'px'
        width += slideWidth
    }
    if (this.loop && !isResize) {
        width += 2 * slideWidth
    }
    this.$refs.slideGroup.style.width = width + 'px'
}

初始化 slide 宽度后可以初始化 better-scroll 了

// 这个配置直接直接看文档就好了,这里我们监听了 scrollEnd 事件获取当前页数
this.slider = new BScroll(this.$refs.slide, {
    scrollX: true,
    scrollY: false,
    momentum: false,
    snap: {
        loop: this.loop,
        threshold: this.threshold,
        speed: this.speed
    }
})

this.slider.on('scrollEnd', () = >{
    this.currentPageIndex = this.slider.getCurrentPage().pageX
    if (this.autoPlay) this._play()
})

初始化 dot

// 初始化对应轮播数量的 dot 即可
this.dots = new Array(this.children.length)

自动播放

// 通过定时器调用 next 接口即可
clearTimeout(this.timer)
this.timer = setTimeout(() => {
  this.slider.next()
}, this.interval)

mounted 阶段初始化,并且监听 resize 事件

setTimeout(() = >{
    this._setSliderWidth() 
    if (this.showDot) this._initDots() 
    this._initSlider()

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

window.addEventListener('resize', () = >{
    if (!this.slider) return 
    this._setSliderWidth(true) 
    this.slider.refresh()
})

还有一个注意的点,当组件中用到了计时器时,要在 destroyed 阶段清除定时器,释放内存

destoryed() {
  clearTimeout(this.timer)
}

然后我们再父组件引用 slider 组件即可


不得不说 better-scroll 真的很强大,最终的展示效果如下:

slider.gif

你可能感兴趣的:(轮播组件——基于原生 && Vue)