You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

构建带相邻页码的分页项:首尾页码场景下的分页逻辑异常修正求助

Pagination Function Display Issue for First/Last Page

我正在编写一个返回分页项的函数,参考了Material-UI的分页实现思路,代码如下:

const pagination = (totalPages, siblingCount = 2, pageNumber) => {
  const ELLIPSIS = '…';
  const siblingsStart = Math.max(
    Math.min(
      // Natural start
      pageNumber - siblingCount,
      // Lower boundary when page is high
      totalPages - siblingCount * 2 - 2,
    ),
    // Greater than startPage
    3,
  );
  const siblingsEnd = Math.min(
    Math.max(
      // Natural end
      pageNumber + siblingCount,
      // Upper boundary when page is low
      siblingCount * 2 + 3,
    ),
    // Less than endPages
    totalPages - 2,
  );

  // Basic list of items to render
  return [
    1,
    // Start ellipsis
    // eslint-disable-next-line no-nested-ternary
    ...(siblingsStart > 3 ? [ELLIPSIS] : totalPages - 1 > 2 ? [2] : []),
    // Sibling pages
    ...range(siblingsStart, siblingsEnd),
    // End ellipsis
    // eslint-disable-next-line no-nested-ternary
    ...(siblingsEnd < totalPages - 2 ? [ELLIPSIS] : totalPages - 1 > 1 ? [totalPages - 1] : []),
    totalPages,
  ];
};

这个函数在中间页码场景下工作正常,比如当pageNumber = 6且totalPages = 20时,返回[1, '…', 4, 5, 6, 7, 8, '…', 20],符合我显示当前页码前后各2个相邻页码的需求。

但在首尾页码场景下显示不符合预期:

  • 当pageNumber = 1时,我期望返回[1, 2, 3, '…', 20],但实际得到[1, 2, 3, 4, 5, 6, 7, '…', 20];
  • 当pageNumber = 20时,期望返回[1, '…', 18, 19, 20],实际结果也不符合预期。

请问如何修正这个函数来满足需求?


Fixing the Pagination Function for First/Last Page Cases

我来帮你解决这个分页函数的首尾页显示异常问题。原代码的核心问题在于没有针对当前页码是第一页或最后一页的场景做特殊处理,导致计算出的页码范围超出了预期。我们可以通过拆分场景来简化逻辑,同时保证所有情况都符合需求:

修正后的完整代码

// 辅助函数:生成从start到end的连续数字数组
const range = (start, end) => {
  const length = end - start + 1;
  return Array.from({ length }, (_, i) => start + i);
};

const pagination = (totalPages, siblingCount = 2, pageNumber) => {
  const ELLIPSIS = '…';
  
  // 情况1:总页数太少,不需要省略号,直接返回所有页码
  if (totalPages <= siblingCount * 2 + 3) {
    return range(1, totalPages);
  }

  // 情况2:当前是第一页或紧邻第一页的页码
  if (pageNumber <= siblingCount + 1) {
    return [
      ...range(1, siblingCount + 2),
      ELLIPSIS,
      totalPages
    ];
  }

  // 情况3:当前是最后一页或紧邻最后一页的页码
  if (pageNumber >= totalPages - siblingCount) {
    return [
      1,
      ELLIPSIS,
      ...range(totalPages - siblingCount - 1, totalPages)
    ];
  }

  // 情况4:中间页码,保留原需求的前后siblingCount个页码
  const siblingsStart = pageNumber - siblingCount;
  const siblingsEnd = pageNumber + siblingCount;

  return [
    1,
    ELLIPSIS,
    ...range(siblingsStart, siblingsEnd),
    ELLIPSIS,
    totalPages
  ];
};

关键修改说明

  1. 总页数阈值判断:当总页数≤siblingCount*2+3时(比如siblingCount=2时总页数≤7),直接返回所有页码,避免没必要的省略号,体验更友好。
  2. 第一页专属逻辑:当当前页码在第一页及相邻的siblingCount个页码内时,只显示前siblingCount+2个页码(比如siblingCount=2时显示1、2、3),接着加省略号和最后一页,完全符合你的预期。
  3. 最后一页专属逻辑:当当前页码在最后一页及相邻的siblingCount个页码内时,显示第一页、省略号,然后显示最后siblingCount+2个页码(比如siblingCount=2时显示18、19、20)。
  4. 简化中间页码逻辑:中间页码的场景直接取当前页码前后siblingCount个页码,两边加省略号和首尾页,逻辑比原代码更清晰易懂。

验证你的测试场景

  • pageNumber=1, totalPages=20 → 返回 [1, 2, 3, '…', 20],符合预期;
  • pageNumber=20, totalPages=20 → 返回 [1, '…', 18, 19, 20],符合预期;
  • pageNumber=6, totalPages=20 → 返回 [1, '…', 4, 5, 6, 7, 8, '…', 20],和原正确结果一致;
  • totalPages=5 → 返回 [1,2,3,4,5],无需省略号,逻辑合理。

内容的提问来源于stack exchange,提问作者Renaud is Not Bill Gates

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 23:07:45