輪播組件——基于原生 && Vue

基于 better-scroll 的輪播圖組件

在做移動(dòng)端輪播圖的時(shí)候,本想沿用之前 PC 端的輪播圖,后來(lái)發(fā)現(xiàn)并沒(méi)有支持 touch 事件,所以采用了 better-scroll 來(lái)實(shí)現(xiàn)輪播圖組件。

關(guān)于 better-scroll 的介紹可以看官方文檔 傳送門

正如 文檔中所說(shuō),學(xué)習(xí) bette-scroll 的相關(guān)組件 最好的方式就是去看 example 目錄下的 demo,我現(xiàn)在要實(shí)現(xiàn)輪播圖組件,直接找到輪播圖的 demo 代碼部分 源碼傳送門

image.png

首先實(shí)現(xiàn)輪播圖的基本思路是通過(guò) width 設(shè)置 overflow: hidden 來(lái)達(dá)到目的,通過(guò) translate 移動(dòng)圖片實(shí)現(xiàn)輪播,這里 translate 的事情 better-scroll 已經(jīng)替我們干了

首先看下輪播圖的 html 結(jié)構(gòu):

<div class="slide" ref="slide">
    <div class="slide-group" ref="slideGroup">
      <slot></slot>    // 通過(guò) slot 父組件傳入圖片等自定義內(nèi)容
    </div>
    <div v-show="showDot" class="dots">
      <span class="dot"      // 圖片對(duì)應(yīng)的下標(biāo)
            :class="{active: currentPageIndex === index}"
            v-for="(item, index) in dots"
            :key="index"
      ></span>
    </div>
  </div>

css 結(jié)構(gòu)采用的是 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 的文檔,就會(huì)知道 better-scroll 執(zhí)行的時(shí)機(jī)是 dom 結(jié)構(gòu)渲染完畢后,所以最好的執(zhí)行時(shí)機(jī)可以通過(guò) this.$nextTick() 去實(shí)現(xiàn),當(dāng)然也可以通過(guò)定時(shí)器 setTimeout(fn, 20) 這樣一個(gè)經(jīng)驗(yàn)值去實(shí)現(xiàn)也是沒(méi)有問(wèn)題的。

確定好了執(zhí)行時(shí)機(jī),我們開(kāi)始初始化相關(guān)內(nèi)容,比如輪播容器寬度以及 better-scroll 等

初始化 slide 寬度

// 獲取圖片的 clientWidth
// 當(dāng)需要循環(huán)播放的時(shí)候在首尾添加兩個(gè)圖片的 clientWidth,做一個(gè)過(guò)渡
// 給整個(gè) slideGroup 設(shè)置 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 了

// 這個(gè)配置直接直接看文檔就好了,這里我們監(jiān)聽(tīng)了 scrollEnd 事件獲取當(dāng)前頁(yè)數(shù)
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

// 初始化對(duì)應(yīng)輪播數(shù)量的 dot 即可
this.dots = new Array(this.children.length)

自動(dòng)播放

// 通過(guò)定時(shí)器調(diào)用 next 接口即可
clearTimeout(this.timer)
this.timer = setTimeout(() => {
  this.slider.next()
}, this.interval)

mounted 階段初始化,并且監(jiān)聽(tīng) 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()
})

還有一個(gè)注意的點(diǎn),當(dāng)組件中用到了計(jì)時(shí)器時(shí),要在 destroyed 階段清除定時(shí)器,釋放內(nèi)存

destoryed() {
  clearTimeout(this.timer)
}

然后我們?cè)俑附M件引用 slider 組件即可

<div v-if="recommends.length" class="slider-wrapper">
   <div class="slider-content">
     <slider>
       <div v-for="(item, index) in recommends" :key="index">
         <a :href="item.linkUrl">
           <img :src="item.picUrl">
         </a>
       </div>
     </slider>
   </div>
 </div>

不得不說(shuō) better-scroll 真的很強(qiáng)大,最終的展示效果如下:

slider.gif
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 謝謝作者的文章 非常喜歡 請(qǐng)?jiān)试S收藏! 博客園首頁(yè)博問(wèn)閃存新隨筆訂閱管理 vue之better-scroll的封裝...
    peng凱閱讀 16,698評(píng)論 2 5
  • 最近在跟著視頻補(bǔ)習(xí)Vue。仿QQ音樂(lè)上的輪播圖。用了better-scroll HTML部分,主要是三個(gè)部分。sl...
    考古羊閱讀 5,237評(píng)論 1 1
  • 說(shuō)課稿:My Favourite Toy第一課時(shí) 一:說(shuō)教學(xué)內(nèi)容 尊敬的各位評(píng)委好! 今天我說(shuō)課的教材內(nèi)容是川教...
    指尖蝶舞的花園閱讀 1,531評(píng)論 0 0
  • BGM=馬頔x大雁 給我一個(gè)復(fù)古玻璃杯,將杯子盛滿38C的清咖啡,我想跟自(ji)己(ji)個(gè)(ge)說(shuō)點(diǎn)悄悄話。...
    花旦十三幺閱讀 400評(píng)論 0 0
  • One 閨蜜之前一直有個(gè)習(xí)慣,什么事情都會(huì)精打細(xì)算,每次用完一筆錢,總會(huì)想自己還剩下多少錢,每個(gè)人要存在多少錢,她...
    徐徐來(lái)閱讀 8,126評(píng)論 37 179

友情鏈接更多精彩內(nèi)容