better-scroll实现列表联动(移动端)

在移动端手机滑动浏览列表是没有滚动条的,那么如何实现没有滚动条又能够滚动呢?

这时候会用到一个常用的插件:better-scroll,利用它来实现移动端的滚动。其原理是利用translate来实现滚动,看下调试:在这里插入图片描述
这个div是需要滚动的列表的父元素,transition-timing-function是为了让translate这个过渡效果更像原生scroll。

使用这个组件你需要有特定的结构,借一张图:better-scroll实现列表联动(移动端)_第1张图片
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实现列表联动(移动端)_第2张图片
然后来实现:右联左
右边在滚动时我们需要知道它滚动了多少距离,滚动到了哪里,(右边属于列表套列表,大列表是分类,小列表是具体商品)
滚动的距离可以通过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 表index值为小列表a的索引值;

初始化一个数组用于存储小列表距离顶部的距离:

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

js:

 1
82

css:

 1