在移动端手机滑动浏览列表是没有滚动条的,那么如何实现没有滚动条又能够滚动呢?
这时候会用到一个常用的插件:better-scroll,利用它来实现移动端的滚动。其原理是利用translate来实现滚动,看下调试:
这个div是需要滚动的列表的父元素,transition-timing-function是为了让translate这个过渡效果更像原生scroll。
使用这个组件你需要有特定的结构,借一张图:
wrpper有固定高度content区超出隐藏;
使用时首先引入better-scroll插件:
import Better from 'better-scroll
传入dom节点对象:
new Better(wrpper)
wrpper节点对象可以是自己找到的对象,赋值给一个变量并传入,也可以传入节点的class名或者id它会自动调用querySelector方法去找节点,还可以通过$refs来查找。
给节点设置ref
new Better(this.$refs.list)
这样改wrpper内部的content区就可以实现滚动了;
然后来看看这种效果:
左右两个列表,左边点击右边跳到相应位置,右边滚动左边相应位置也高亮显示;这就是典型的列表联动。
我们将它分解一下,先实现左联右:
用到better-scroll中的 scrollToElement(el,time,offsetX,offsetY,easing) 很简单的方法拿来即用
1、在需要跳转到的区块上添加ref属性用于标识
1
2
3 {{it.name}}
4
5
6 -
7
8
9
10
{{item.name}}
11 {{item.description}}
12 月售{{item.sellCount}}份好评率{{item.rating}}%
13 ¥{{item.price}}
14
15
16
17
18
19
2、定义方法跳转到相应位置
1methods: {
2 change (index) {
3 this.actli = index
4 this.rgt.scrollToElement(this.$refs.good[index], 100, 0, 0)
5 },
6}
3、左列表点击调用
1
记住左侧滚动栏的better-scroll对象要开启点击事件
1 this.left = new Better(this.$refs.l_list, {
2 click: true //开启点击事件
3 })
然后来实现:右联左
右边在滚动时我们需要知道它滚动了多少距离,滚动到了哪里,(右边属于列表套列表,大列表是分类,小列表是具体商品)
滚动的距离可以通过better-scroll对象的scroll事件的回调函数的参数取得;
1 this.rgt = new Better(this.$refs.r_list, {
2 click: true,
3 probeType: 3//实时分发scroll事件
4 })
5 this.rgt.on('scroll', (res) => {
6 console.log(res)
7 this.scrollY = Math.abs(res.y)
8 })
probeType属性具体可参考官网文档,在此不再累述
可以看到参数res是一个对象,对象内包含x,y,即滚动的x轴和y轴的距离。
知道了滚动了多少距离,还要知道滚动到了哪里,即大列表的index值;我们可以拿content滚动的距离和每个小列表距离顶部的距离作比较;
设content滚动距离为x,小列表a距离顶部的距离为La,小列表b距离顶部的距离为Lb(小列表a是小列表b的前一项),那么当La
初始化一个数组用于存储小列表距离顶部的距离:
1 data () {
2 return {
3 actli: 0,
4 arr: [0],
5 }
6 },
将距离存储到arr中:
1 mounted () {
2 this.$refs.good.forEach((el, index) => {
3 this.arr.push(el.offsetHeight + this.arr[index])
4 })
5}
比较并更新index:
1 this.rgt.on('scroll', (res) => {
2 if (this.flag) {
3 console.log(res)
4 this.scrollY = Math.abs(res.y)
5 for (let i = 0; i < this.arr.length; i++) {
6 if (this.scrollY > this.arr[i] && this.scrollY < this.arr[i + 1]) {
7 this.actli = i
8 }
9 }
10 }
11 })
考虑到数据的异步请求,以及左侧列表增加动态性更完整的代码如下:
1mounted () {
2 setTimeout(() => {
3 /* eslint-disable no-new */
4 this.left = new Better(this.$refs.l_list, {
5 click: true //开启点击事件(默认关闭)
6 })
7 this.rgt = new Better(this.$refs.r_list, {
8 click: true,
9 probeType: 3 //scroll事件实时分发
10 })
11 this.$refs.good.forEach((el, index) => {//计算每个列表相对于顶部的距离,存到数组arr中
12 this.arr.push(el.offsetHeight + this.arr[index])
13 })
14 this.rgt.on('scroll', (res) => {//监听滚动事件
15 if (this.flag) {
16 this.scrollY = Math.abs(res.y)
17 for (let i = 0; i < this.arr.length; i++) {
18 if (this.scrollY > this.arr[i] && this.scrollY < this.arr[i + 1]) {
19 this.actli = i
20 if (i === this.$refs.l_item.length - 2) {//当滚动到倒数第2个位置时左侧列表向上滚动一个距离
21 this.left.scrollToElement(this.$refs.l_item[1], 100, 0, 0)
22 }
23 if (i === 2) {//当滚动到倒数第3个位置时左侧列表向上下滚动一个距离
24 this.left.scrollToElement(this.$refs.l_item[0], 100, 0, 0)
25 }
26 }
27 }
28 }
29 })
30 })
31 }
附goods组件全部代码:
template:
1
2
3
13
14
15
16
17 {{it.name}}
18
19
20 -
21
22
23
24
{{item.name}}
25 {{item.description}}
26 月售{{item.sellCount}}份好评率{{item.rating}}%
27 ¥{{item.price}}
28
29
30
31
32
33
34
35
36
37
js:
1
82
css:
1