首頁  >  文章  >  web前端  >  怎樣用Vue+better-scroll實現字母索引導航

怎樣用Vue+better-scroll實現字母索引導航

php中世界最好的语言
php中世界最好的语言原創
2018-05-23 11:40:252416瀏覽

這次帶給大家怎樣用Vue better-scroll實現字母索引導航,用Vue better-scroll實現字母索引導航的注意事項有哪些,下面就是實戰案例,一起來看一下。

Demo:list-view,使用 chrome 手機模式檢視。換成手機模式之後,不能滑動的話,刷新一下就 OK 了。

Github: 行動端字母索引導覽

效果圖

設定環境


因為用到的是vue-cli 和better-scroll,所以首先要安裝vue-cli,然後再npm 安裝better-scroll。

簡單介紹一下 better-scroll:

better-scroll 是一款重點解決行動裝置(已支援 PC)各種捲動場景需求的外掛程式。它的核心是藉鑒的 iscroll 的實現,它的 API 設計基本上兼容 iscroll,在 iscroll 的基礎上又擴展了一些 feature 以及做了一些

性能優化

better-scroll 是基於原生 JS 實作的,不依賴任何框架。它編譯後的程式碼大小是 63kb,壓縮後是 35kb,gzip 後僅有 9kb,是一款非常輕量的 JS lib。 除了這兩,還使用 scss、vue-lazyload。 scss 預處理器,大家都懂,用別的也一樣。 lazyload 實現懶加載,不用也可以,主要是優化一下體驗。

資料直接使用了網易雲的歌手榜單,偷懶就直接放在 data 裡面了。

CSS 樣式我就不貼了,直接看原始碼就可以了。

實作基本樣式

直接使用 v-for 和 雙側嵌套實作歌手清單、以及右側索引列。 HTML 結構:

<ul>
 <li v-for="group in singers" 
 class="list-group" 
 :key="group.id" 
 ref="listGroup">
  <h2 class="list-group-title">{{ group.title }}</h2>
  <ul>
   <li v-for="item in group.items" 
   class="list-group-item" :key="item.id">
    <img v-lazy="item.avatar" class="avatar">
    <span class="name">{{ item.name }}</span>
   </li>
  </ul>
 </li>
</ul>
<p class="list-shortcut">
 <ul>
  <li v-for="(item, index) in shortcutList"
  class="item"
  :data-index="index"
  :key="item.id"
  >
   {{ item }}
  </li>
 </ul>
</p>
shortcutList 是透過計算屬性得到的,取 title 的第一個字元即可。

shortcutList () {
 return this.singers.map((group) => {
  return group.title.substr(0, 1)
 })
}

使用 better-scroll

#使用 better-scroll 實作捲動。對了,使用的時候別忘了用 import 引入。

created () {
 // 初始化 better-scroll 必须要等 dom 加载完毕
 setTimeout(() => {
  this._initSrcoll()
 }, 20)
},
methods: {
 _initSrcoll () {
  console.log('didi')
  this.scroll = new BScroll(this.$refs.listView, {
   // 获取 scroll 事件,用来监听。
   probeType: 3
  })
 }
}
使用 created 方法進行 better-scroll 初始化,使用 setTimeout 是因為需要等到 DOM 載入完畢。不然 better-scroll 取得不到 dom 就會初始化失敗。 這裡把方法寫在兩個 methods 裡面,這樣就不會看起來很亂,直接呼叫就可以了。 初始化的時候傳入兩 probeType: 3,解釋一下:當 probeType 為 3 的時候,不僅在屏幕滑動的過程中,而且在 momentum 滾動動畫運行過程中實時派發 scroll 事件。如果沒有設定該值,其預設值為 0,即不派發 scroll 事件。

為索引新增點擊事件和移動事件實作跳躍

首先需要給索引綁定一個touchstart 事件(當在螢幕上按下手指時觸發),直接使用v-on 就可以了。然後還要為索引加上一個 data-index 這樣就可以取得到索引的值,使用 :data-index="index" 。 ###
<p class="list-shortcut">
 <ul>
  <li v-for="(item, index) in shortcutList"
  class="item"
  :data-index="index"
  :key="item.id"
  @touchstart="onShortcutStart"
  @touchmove.stop.prevent="onShortcutMove"
  >
   {{ item }}
  </li>
 </ul>
</p>
###綁定一個 onShortcutStart 方法。實現點選索引跳轉的功能。再綁定一個 onShortcutMove 方法,實現滑動跳轉。 ###
created () {
 // 添加一个 touch 用于记录移动的属性
 this.touch = {}
 // 初始化 better-scroll 必须要等 dom 加载完毕
 setTimeout(() => {
  this._initSrcoll()
 }, 20)
},
methods: {
 _initSrcoll () {
  this.scroll = new BScroll(this.$refs.listView, {
   probeType: 3,
   click: true
  })
 },
 onShortcutStart (e) {
  // 获取到绑定的 index
  let index = e.target.getAttribute('data-index')
  // 使用 better-scroll 的 scrollToElement 方法实现跳转
  this.scroll.scrollToElement(this.$refs.listGroup[index])
  // 记录一下点击时候的 Y坐标 和 index
  let firstTouch = e.touches[0].pageY
  this.touch.y1 = firstTouch
  this.touch.anchorIndex = index
 },
 onShortcutMove (e) {
  // 再记录一下移动时候的 Y坐标,然后计算出移动了几个索引
  let touchMove = e.touches[0].pageY
  this.touch.y2 = touchMove
  
  // 这里的 16.7 是索引元素的高度
  let delta = Math.floor((this.touch.y2 - this.touch.y1) / 18)
  // 计算最后的位置
  // * 1 是因为 this.touch.anchorIndex 是字符串,用 * 1 偷懒的转化一下
  let index = this.touch.anchorIndex * 1 + delta
  this.scroll.scrollToElement(this.$refs.listGroup[index])
 }
}
###這樣就可以實現索引的功能了。 ######當然這樣是不會滿足我們的對不對,我們要加入酷炫的特效呀。例如索引高亮什麼的~~############移動內容索引高亮############emmm,這時候就有點複雜啦。但是有耐心就可以看懂滴。 ######我們需要 better-scroll 的 on 方法,傳回內容捲動時候的 Y軸偏移值。所以在初始化 better-scroll 的時候需要加入一下程式碼。對了,別忘了在 data 中加入一個 scrollY,和 ###current###Index (用來記錄高亮索引的位置)因為我們需要監聽,所以在 data 中加入。 ###
_initSrcoll () {
 this.scroll = new BScroll(this.$refs.listView, {
  probeType: 3,
  click: true
 })
 // 监听Y轴偏移的值
 this.scroll.on('scroll', (pos) => {
  this.scrollY = pos.y
 })
}
###然後需要計算內容的高度,增加一個 calculateHeight() 方法,用來計算索引內容的高度。 ###
_calculateHeight () {
 this.listHeight = []
 const list = this.$refs.listGroup
 let height = 0
 this.listHeight.push(height)
 for (let i = 0; i < list.length; i++) {
  let item = list[i]
  height += item.clientHeight
  this.listHeight.push(height)
 }
}
// [0, 760, 1380, 1720, 2340, 2680, 2880, 3220, 3420, 3620, 3960, 4090, 4920, 5190, 5320, 5590, 5790, 5990, 6470, 7090, 7500, 7910, 8110, 8870]
// 得到这样的值

然后在 watch 中监听 scrollY,看代码:

watch: {
 scrollY (newVal) {
  // 向下滑动的时候 newVal 是一个负数,所以当 newVal > 0 时,currentIndex 直接为 0
  if (newVal > 0) {
   this.currentIndex = 0
   return
  }
  // 计算 currentIndex 的值
  for (let i = 0; i < this.listHeight.length - 1; i++) {
   let height1 = this.listHeight[i]
   let height2 = this.listHeight[i + 1]
   if (-newVal >= height1 && -newVal < height2) {
    this.currentIndex = i
    return
   }
  }
  // 当超 -newVal > 最后一个高度的时候
  // 因为 this.listHeight 有头尾,所以需要 - 2
  this.currentIndex = this.listHeight.length - 2
 }
}

得到 currentIndex 的之后,在 html 中使用。

给索引绑定 class -->  :class="{'current': currentIndex === index}"

最后再处理一下滑动索引的时候改变 currentIndex。

因为代码可以重复利用,且需要处理边界情况,所以就把

this.scroll.scrollToElement(this.$refs.listGroup[index])

重新写了个函数,来减少代码量。

// 在 scrollToElement 的时候,改变 scrollY,因为有 watch 所以就会计算出 currentIndex
scrollToElement (index) {
 // 处理边界情况
 // 因为 index 通过滑动距离计算出来的
 // 所以向上滑超过索引框框的时候就会 < 0,向上就会超过最大值
 if (index < 0) {
  return
 } else if (index > this.listHeight.length - 2) {
  index = this.listHeight.length - 2
 }
 // listHeight 是正的, 所以加个 -
 this.scrollY = -this.listHeight[index]
 this.scroll.scrollToElement(this.$refs.listGroup[index])
}

lazyload

lazyload 插件也顺便说一下哈,增加一下用户体验。

使用方法

先 npm 安装

在 main.js 中 import,然后 Vue.use

import VueLazyload from 'vue-lazyload'
Vue.use(VueLazyload, {
 loading: require('./common/image/default.jpg')
})

添加一张 loading 图片,使用 webpack 的 require 获取图片。

然后在需要使用的时候,把 :src="" 换成 v-lazy="" 就实现了图片懒加载的功能。

总结

移动端字母索引导航就这么实现啦,感觉还是很有难度的哈(对我来说)。

主要就是使用了 better-scroll 的 on 获取移动偏移值(实现高亮)、scrollToElement 跳转到相应的位置(实现跳转)。以及使用 touch 事件监听触摸,来获取开始的位置,以及滑动距离(计算最后的位置)。

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

vue2.0实现输入框实时检索更新步骤详解

mpvue小程序markdown适配怎样实现

以上是怎樣用Vue+better-scroll實現字母索引導航的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn