Vue滑動翻頁組件swiper的實現---第一版

關於滑動翻頁,有很多優秀的插件可以使用,但是多多少少都有點大,所以自己試着完成一個組件來實現。(以左右滑動翻頁爲例)

1、主要思路

        最主要的就是對三個觸摸事件的處理:touchstart、touchmove、touchend

        在touchstart事件處理程序中記錄一些初始值,比如原始座標;在touchmove事件處理程序中計算實時滑動的距離,讓元素隨之一起偏移;在touchend事件處理程序中計算最終的滑動距離,大於闕值則滑動一整頁,小於則回到起始位置。

2、代碼實現

        頁面結構:具體的組件結構和數據傳遞就不展示了,只列出編譯後的HTML結構如下:

        基本樣式:inline-block用font-size: 0來隱藏間距

​
<style lang='scss'>
.ths_swiper-wrap {
  white-space: nowrap;
  display: inline-block;
  font-size: 0;
  .swiper{
    position: relative;
    display: inline-block;
    width: 100vw;
    text-align: center;
    font-size: 14px;
  }
}
</style>

​

        初始設置:記錄頁面寬度、.ths_swiper-wrap元素的寬度、滾動的元素.swiper

mounted () {
    this.pageWidth = document.documentElement.clientWidth
    this.elementWidth = this.$refs.swiper.offsetWidth
    this.swiperEles = this.$refs.swiper.querySelectorAll('.swiper')
},

        滾動元素:這裏需要專門記錄的是,在.ths_swiper-wrap元素上監聽滑動事件,.ths_swiper-wrap元素和.swiper元素滑動時都會觸發。所以我一開始是使用.self修飾符,只監聽.ths_swiper-wrap元素的滾動,移動的也是.ths_swiper-wrap元素。

<div class="ths_swiper-wrap"
    ref="swiper"
    @touchstart.self="touchstart"
    @touchmove.self="touchmove"
    @touchend.self="touchend">
    <slot></slot>
</div>

        但是這樣做會有個問題,手指點在.swiper元素上時無法滑動,只有點在.swiper外 && .ths_swiper-wrap內(.ths_swiper-wrap的padding,或.swiper的margin)時才能滑動。所以,最終我選擇不是滑動.ths_swiper-wrap元素,而是滑動全部.swiper元素。

<div class="ths_swiper-wrap"
    ref="swiper"
    @touchstart="touchstart"
    @touchmove="touchmove"
    @touchend="touchend">
    <slot></slot>
</div>

        事件處理

touchstart (e) {
  this.originalPos = e.touches[0].pageX
  this.originalLeft = Number(this.swiperEles[0].style.left.split('px')[0])
},
touchmove (e) {
  this.doSlide((e.touches[0].pageX - this.originalPos) / 2) // 除以2來控制滑動速度
},
touchend (e) {
  let moveDistance = e.changedTouches[0].pageX - this.originalPos // >0 右滑,<0 左滑
  let currentLeft = Number(this.swiperEles[0].style.left.split('px')[0])
  if ((Math.abs(moveDistance) > 100 && ((moveDistance > 0 && currentLeft < 0) || (moveDistance < 0 && Math.abs(currentLeft) < this.elementWidth - this.pageWidth)))) {
    // 滑動距離大於闕值100,且內容在邊界內時,滑動一整頁
    let distance = moveDistance > 0 ? this.pageWidth : -this.pageWidth
    this.doSlide(distance)
  } else {
    // 滑動回原處
    this.doSlide(0)
  }
},
doSlide (distance) {
  this.swiperEles.forEach((element, index) => {
    element.style.left = this.originalLeft + distance + 'px'
  })
}

3、後期優化

        上面實現了最基礎的滑動翻頁組件,算是第一版,後期還有很多需要優化的地方,比如每個.swiper元素的高度如果不統一,父級高度應該自適應;滑動時爲了提升性能,不需要滑動所有.swiper元素,只需要滑動當前和即將要進入的兩個元素即可等等。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章