微信小程序&移动端的触底分页&下拉刷新

96 阅读4分钟

微信小程序&移动端的触底分页&下拉刷新

  1. 首先需要定义一个变量用来表示当前数据获取的状态 eg: status:['nomore','more','loading','error'] // 设定status的初始值为more

  2. 其次书写获取列表数据的方法 a. 先修改status的值为loading,代表我们的请求正在加载中 b. 然后发请求获取数据,判断返回的数据长度 i. 如果长度大于0,说明请求的数据还有,此时有两种情况 1. 如果返回的数据长度小于我们发请求时的pageSize,则说明此时数据已经完全加载,没有更多的数据了,需要修改status为nomore 2. 如果返回的数据长度等于我们发请求时的pageSize,并不能说明下一页还有数据,只能说明这次发请求返回的数据满足所需要的数据条数,但下一页的数据是否还有我们不能判断,可以继续发送下一页的请求在来判断,需要修改status为more,然后将pageNumber++ 3. 在数据返回时,我们需要将列表展示的data进行赋值: 此时需要注意的是,如果是vue2,我们需要用this.list.push(result.data)来添加数据,因为vue2中对于响应式数组数据需要使用数组方法来修改,不能通过赋值来实现 如果是vue3,且是组合式API写法,可以直接list.value = [...list.value, ...result.data] 来添加数据 ii. 如果长度等于0,则说明请求的数据为空,则代表数据已经完全加载,没有更多的数据了,此时需要修改status为nomore iii. 如果走到了catch里面,则说明我们的请求出错了,此时就需要修改status为error

  3. status状态判断

    • 当status为nomore时,说明没有数据了,所以就不需要再发请求
    • 当status为error时,说明请求发送失败了,也不需要在发请求
    • 当status为loading时,也不要在多次发送请求。eg:用户一直进行触底的操作,如果为loading时继续发送请求,则会有多个返回,顺序无法确定,以及会造成数据的混乱等 小程序中:
      • 我们可以使用onReachBottom函数,它会自动判断我们是否已经触底,然后当status为more时,我们在发请求获取下一页的数据
      • 我们可以使用onPullRefresh函数,直接将pageNumber变为1,然后发送请求就可以了 移动端中(拿vant组件举例):
      • vue3配合vant组件没有像小程序那样直接的触底函数,van-list组件有load方法,是进行数据加载的
      • 我们可以采用类似小程序的方法,然后再load方法中,去进行status的判断然后再抓取数据,就能达到和小程序中相同的效果
      • 当下拉刷新时,我们可以采用van-pull-refresh组件的refresh方法,将finished变为false,然后将数据清空,在将页码变为1,在抓取数据就可以了。

综上所述,我们在进行触底分页时,需要设置一个status用来判断是否继续获取分页的数据,然后通过数据返回的长度与pageSize比较来修改status的值,进而在触底时进行获取数据的控制

移动端代码:

<template>
  <div>
    <van-pull-refresh v-model="refreshing" @refresh="onRefresh">
      <van-list
        v-model:loading="loading"
        :finished="finished"
        finished-text="没有更多了"
        @load="onLoad"
        :offset="100"
        :immediate-check="false"
      >
        <van-cell v-for="item in list" :key="item" :title="item" />
      </van-list>
    </van-pull-refresh>
  </div>
</template>

<script setup>
import { onMounted, reactive, ref } from 'vue';
const list = ref([])
const loading = ref(false)
const finished = ref(false)
const refreshing = ref(false);
const requestStatus = ref('more')
const searchParams = reactive({
  page: 1,
  page_size: 10
})
onMounted(() => {
  initLoad()
})
const initLoad = async () => {
  try {
    requestStatus.value = 'loading'
    loading.value = true
    const res = await getMyLeaveForm(searchParams)
    if(res) {
      let detailData = JSON.parse(res)
      if(detailData.result.length > 0) {
        if(detailData.result.length < searchParams.page_size){
          requestStatus.value = 'nomore'
          finished.value = true
        }else {
          requestStatus.value = 'more'
          searchParams.page++
        }
        list.value = [...list.value, ...detailData.result]
        loading.value = false
        refreshing.value = false
      }else {
        requestStatus.value = 'nomore'
        finished.value = true
      }
    } 
  } catch (error) {
    requestStatus.value = 'error'
  }
}
const onLoad = () => {
  requestStatus.value === 'more' && initLoad()
}
const onRefresh = () => {
  // 清空列表数据
  finished.value = false;
  list.value = []
  // 重新加载数据
  // 将 loading 设置为 true,表示处于加载状态
  loading.value = true;
  searchParams.page = 1
  initLoad();
};
</script>

小程序端代码:

import { findGoodList } from "../../../utils/api";
Page({

  /**
   * 页面的初始数据
   */
  data: {
    goodList: [], // 商品列表
    page: 1, // 分页的页码
    limit: 10, // 每页的个数
    loadStatus: 'more', // more(可能还有) | nomore(后边一定没有了) | loading(正在加载) | error(加载错误)
    category2Id: '', // 商品分类的二级id
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {
    // console.log('options: ', options);
    options.category2Id && this.setData({
      category2Id: options.category2Id
    })
    this.getGoodList();
  },
  /* 获取goodList的功能函数 */
  async getGoodList() {
    try {
      let { page, limit, goodList, category2Id } = this.data;
      // 修改loadStatus状态
      this.setData({
        loadStatus: 'loading'
      })
      let result = await findGoodList({ page, limit, category2Id });
      if (result.code === 200) {
        let records = result.data.records;
        
        if (records.length > 0) {
          if (records.length === limit) { // 后边可能还有数据
            this.setData({
              loadStatus: 'more'
            })
          } else {
            this.setData({
              loadStatus: 'nomore'
            })
          }

          goodList.push(...records);
          this.setData({
            goodList,
            page: ++page
          })

        } else { // 当前获取的是空数组
          this.setData({
            loadStatus: 'nomore'
          })
        }
      } else {
        this.setData({
          loadStatus: 'error'
        })
      }
    } catch (error) {
      console.log(error);
      this.setData({
        loadStatus: 'error'
      })
    }
  },

  /* 页面上拉触底的回调函数 */
  onReachBottom() {
    console.log('页面触底了。。。');
    this.data.loadStatus === 'more' && this.getGoodList();
  }
})

作为一个入行不久的前端开发,以上是小弟的一些见解,期待各位的补充,如果有什么说的不对的地方,也请指出,会及时的更正~ 感谢各位大佬