vue+ better-scroll 实现移动端歌手列表字母索引导航。算是一个学习笔记吧,写个笔记让自己了解的更加深入一点。
Demo:,使用 chrome 手机模式查看。换成手机模式之后,不能滑动的话,刷新一下就 OK 了。
Github: 移动端字母索引导航
效果图
配置环境
因为用到的是 vue-cli 和 better-scroll,所以首先要安装 vue-cli,然后再 npm 安装。
简单介绍一下 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" :key="group.id" ref="listGroup"> <h2>{{ group.title }}</h2> <ul> <li v-for="item in group.items" :key="item.id"> <img v-lazy="item.avatar"> <span>{{ item.name }}</span> </li> </ul> </li> </ul> <div> <ul> <li v-for="(item, index) in shortcutList" :data-index="index" :key="item.id" > {{ item }} </li> </ul> </div>
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" 。
<div> <ul> <li v-for="(item, index) in shortcutList" :data-index="index" :key="item.id" @touchstart="onShortcutStart" @touchmove.stop.prevent="onShortcutMove" > {{ item }} </li> </ul> </div>
绑定一个 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,这个时候就有点复杂啦。但是有耐心就可以看懂滴。