移动端实现分页

2020/01/09 功能实现

列表页分页

我说的移动端的列表分页,并不是像 pc 端那样有一个分页按钮供你选着,有上一页下一页。更多的是像懒加载,第一次只加载一部分数据,滚动到底部的时候如果接口那边还有数据没有加载玩就继续加载,如果已经加载完了,就不加载了。

为什么要分页?

  1. 数据接口需要进行分页,后端数据量特别大,每一次请求接口只会给一部分的数据

  2. 数据接口不需要进行分页,但是给的数据量特别大,渲染慢,用户需要等待很久,但是用户一般只会看前面的数据

第一种情况是被迫的分页,第二种是为了用户体验。现在的移动端分页不像以前,还有一个分页的页脚,你去点击上下页切换,或者页码跳转。现在的分页都是隐藏的,一个产品有没有分页,专业人事才知道

实现原理

  1. 监听滚动事件 onScroll ,滚动条的总高度 >= 可视区的高度+距离顶部的距离,表示滚动到底部,这个时候可以进行接口的数据请求,或者添加一部分的数据到列表中去

  2. 利用 IntersectionObserver 目标元素有没有即将进入我们的视口(用户能不能看到它),即将进入我们的视口,表示已经滚动到了底部,这个时候可以进行接口的数据请求,或者添加一部分的数据到列表中去

两种实现原理只是使用的东西不一样,底层原理是一样的,就是当用户滚动到底部的时候我们进行数据接口的请求。

第一次写分页的时候,我写的不是很好,有大大小小的问题。朋友和我说别急,你想清楚了什么时候分页,慢慢来,想清楚了,你就会写了。果然是这样的。理清了思路写起来就很简单了

第一种方式的关键代码

    // 滚动加载数据
    onScroll(event) {
      const target = event.target
      // 滚动条的总高度
      const scrollHeight = target.scrollHeight
      // 可视区的高度
      const clientHeight = target.clientHeight
      // 距离顶部的距离
      const scrollTop = target.scrollTop
      // 滚动到底部,在安卓机低下有可能有小数,需要取整
      if (Math.ceil(scrollTop + clientHeight) >= scrollHeight) {
        this.getList()// 接口请求或者添加数据到列表中去
      }
    },
      // 获取数据
    getList() {
      if (this.param.page === 1) {
        this.total = 30
        this.param.page++

        // this.$api.Record.applyList(this.param).then(res => {
        //   console.log('接口返回数据', res)
        //   // 模拟数据
        //   if (res.code !== 0) return
        //   let data = res.data
        //   this.total = data.total
        //   this.param.page++
        //   this.list = data.list
        // })
      } else {
        // 根据请求到的数据去判断数据是否请求完了
        this.hasMore = this.list.length < this.total
        if (this.hasMore) {
          const newList = [
            {
              applicationTime: '89239',
              time: 'w2'
            },
            {
              applicationTime: '8929',
              time: '89w832'
            },
            {
              applicationTime: '8939',
              time: '这么8w98232'
            }
          ]
          this.list = [...this.list, ...newList]
          //   this.param.page++
          // this.$api.Record.applyList(this.param).then(res => {
          //   console.log('接口返回数据', res)

          //   if (res.code !== 0) return
          //   let data = res.data
          //   let newList = data.list
          //   this.list = [...this.list, ...newList]
          //   this.param.page++
          // console.log(this.list, '已经加载数据')
          // })
        }
      }
    },

第二种实现方式,关键性代码

    getObserver(){
     const observer = new IntersectionObserver(entry=>{
       if(entry[0]&&entry[0].isIntersecting){
         this.getList()
       }
     });
    observer.observe(document.querySelector('.list-loading-status'))
    },

你喜欢第一种还是第二种,因人而异,看自己喜欢把。第二种更加灵活,他还能做图片的懒加载,没有进入可视区,图片就用占位符占位,进去可视区之后在渲染。在满屏片的图片渲染的时候,这是一个很好的方式。

或许还有朋友喜欢用 touchstart ?这个我没有尝试过,怕麻烦

详情查看 Scroll.vue 和 ScrollIntersection.vue


有时候,虽然素未谋面。却已相识很久,很微妙也很知足。在逝去的岁月里,我们在某一刻,共同经历着一样的情愫。

如果喜欢我的话,我们可以互相关注,相互学习的哟!互相鼓励,你的关注是我最大的动力来源

sunseekers

Search

    Table of Contents