对于无限加载的分页查询在列表有增删的情况下防止下一页元素重复的一种方案

说明

在开发无限加载的功能时, 发现当前列表中的元素有增删会使分页的结果有偏移, 导致后续追加的元素中, 可能会存在当且列表末尾重复的元素, 此时分页查询的参数不适合固定的分页及大小了: 比如此时页码为2, 列表元素20个, 每页加载10个, 此时向列表中添加一个元素, 那么在获取第3页的时候, 上一页末尾的一个元素将与第3页的第一个元素重复

解决方法

想到一种大致可行的方法: 需要实时计算页码和每页的大小; 为了在下一页的元素下标正好从列表末尾后开始, 一个很简单的要素就可以, 就是当前列表长度的最大约数(除自身), 然后就可以计算下一页所需的页码和页大小了

完整代码

使用的Vue的组合式API;
其中size是为了限制约数在页大小范围内

usePage.ts

const findMaxDivisor = (val: number, limit: number): number => {
  // 异常参数的情况
  if (val < 1 || limit < 1) return 1
  const integerVal = Math.floor(val)
  const integerLimit = Math.floor(limit)
  const candidate = Math.ceil(integerVal / integerLimit) * integerLimit - integerVal;
  // 此约数能保证下一页大小与原定大小一致的情况
  if (integerVal % candidate == 0) return candidate
  for (let i = Math.min(Math.floor(integerVal / 2), integerLimit); i >= 2; i--) {
    // 找到符合的约数的情况
    if (integerVal % i == 0) return i;
  }
  // 素数的情况
  return 1;
}

export const usePage = (size: number) => {
  const infinite = (currentLength: number): PageQuery => {
    // 首页
    if (!currentLength) {
      return {
        page: 1,
        size: size
      }
    }
    const nextSize = findMaxDivisor(currentLength, size);
    return {
      page: (currentLength / nextSize) + 1,
      size: nextSize
    }
  }

  return {
    infinite
  }
}

使用

传递分页参数时, 调用infinite()方法, 传递当前列表长度即可

// 每页大小10
const {infinite} = usePage(10)

const fetchPage = ({done}: any): void => {
  post<Page<Release>>(Path.Release.page, infinite(releases.value.length))
    .then(r => {
      if (!r.data.records.length) {
        done('empty')
      } else {
        releases.value.push(...r.data.records)
        done('ok')
      }
    })
    .catch(() => done('error'))
}

效果

一共12个元素:
第一次

{"page":1,"size":10}

第二次

{"page":3,"size":5}

第三次

{"page":3,"size":6}

貌似还有优化的地方, 比如第二次其实size按照10就行, for循环中Math.min(Math.floor(integerVal / 2), integerLimit)取了最小值, 因此变成了5

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值