likes
comments
collection
share

微信小程序:优雅处理分页功能

作者站长头像
站长
· 阅读数 10

背景

在公司的项目中,分页功能十分常见,以前就是简单的复制粘贴,每次来回切换切面,还经常复制错位置或复制到其他页面去了,半天找不到原因(内心:#*! $%^&@ 1)。

核心思路

分页原理:

属性 page来控制分页数,初始值为1;moreFlag有更多数据的标志,初始值为true;pageSize页面自行定义,可以默认设置为10

组件 原生scroll-viewrecycle-view,但内容页面定制化(循环detailList)

方法 bindscrolltolowerbindscrolltoUpper 调取接口获取更多数据,若结果集中的数据量小于pageSize时,moreFlag更新为false,界面激活“暂无更多”标识;bindrefresherrefresh时刷新重置变量为初始值。

后端接口对接 一般接口都会用Promise异步封装,但一般页面中的请求和处理都各不相同,所以不能作为共同点

getListChangeStatus初始化
getList加载数据
getRemoteList调接口输出处理好的结果集
getList合并结果集
下拉刷新重置pulldownRefresh

混入

根据上面的分页原理,大都为逻辑处理,所以考虑使用类似Vue里的混入,而在小程序中有一个类似的语法:Behavior

Behavior

微信小程序:优雅处理分页功能

behaviors 是用于组件间代码共享的特性,类似于一些编程语言中的 “mixins” 或 “traits”。

每个 behavior 可以包含一组属性、数据、生命周期函数和方法。组件引用它时,它的属性、数据和方法会被合并到组件中,生命周期函数也会在对应时机被调用。  每个组件可以引用多个 behavior ,behavior 也可以引用其它 behavior

定义Behavior

和组件的配置参数差不多,点击查看详情

注意 即使运用在Page里,方法也需放在methods里;同时注意一下同名字段和生命周期的规则,如下图所示:

微信小程序:优雅处理分页功能 以 scroll-view 按照分页原理来定义分页的Behavior

module.exports = Behavior({
  data: {
    page: 1,
    moreFlag: true,
    detailList: [],
    refreshFlag: false
  },
  methods: {
    // 初始化
    async getListChangeStatus() {
      this.setData({
        page: 1,
        detailList: [],
        moreFlag: true
      })
      await this.getList()
    },
    // 获取列表
    async getList() {
      if (!this.data.moreFlag) {
        ... // 可以增加处理,例如吐司等
        return
      }
      let { detailList,fun } = await this.getRemoteList()
      if (detailList) {
        let detailListTem = this.data.detailList
        if (this.data.page == 1) {
          detailListTem = []
        }
        if (detailList.length < this.data.pageSize) {
          //表示没有更多数据了
          this.setData({
            detailList: detailListTem.concat(detailList),
            moreFlag: false
          })
        } else {
          this.setData({
            detailList: detailListTem.concat(detailList),
            moreFlag: true,
            page: this.data.page + 1
          })
        }
        // 可能需要一些处理,例如获取容器的高度之类的,又或者scroll-into-view对应id
        if(fun && fun instanceof Function) fun()
      }
    },
    // 到达底部
    reachBottom() {
      console.log('--reachBottom--')
      this.getList()
    },
    // 下拉刷新重置
    pullDownRefresh() {
      this.setData({
        page: 1,
        hasMoreData: true,
        detailList: []
      })
      this.getList()
      setTimeout(() => {
        this.setData({
          refreshFlag: false
        })
      }, 500)
    }
  }
})

引入方法

在页面或组件中(如果页面多个需要分页的地方建议用组件)使用behaviors: [myBehavior]

import pagination from '../../behaviors/pagination.js'
Page({
  data: {
    pageSize: 10
  },
  behaviors: [pagination],
  onShow() {
    this.getListChangeStatus()
  },
  async getRemoteList() {
    let { page, pageSize } = this.data
    const returnObj = {}
    const res = await XXX // 请求接口
    ... // 处理数据
    returnObj.detailList = data
    return returnObj
  }
})

<scroll-view scroll-y refresher-enabled refresher-triggered="{{refreshFlag}}" bindrefresherrefresh="pullDownRefresh" bindscrolltolower="reachBottom" style="height:100%;">
<!--定义内容-->
</scroll-view>

总结