这次给大家带来怎样用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,和 currentindex (用来记录高亮索引的位置)因为我们需要监听,所以在 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 事件监听触摸,来获取开始的位置,以及滑动距离(计算最后的位置)。
相信看了本文案例你已经掌握了方法,更多精彩请关注其它相关文章!
推荐阅读:
vue2.0实现输入框实时检索更新步骤详解
mpvue小程序markdown适配怎样实现
以上就是怎样用vue+better-scroll实现字母索引导航的详细内容。
