推荐用纯函数 getPaginatedData 封装分页逻辑,接收 data、currentPage、pageSize,返回 slice 切片子数组,确保不可变性、可复用、易测试。

分页逻辑该用哪个函数封装?
分页的核心是「从数组中切出当前页的数据」,推荐用一个纯函数 getPaginatedData 处理,不依赖 DOM 或框架状态。它只接收原始数据数组、当前页码 currentPage 和每页条数 pageSize,返回切片后的子数组。
常见错误是把分页逻辑和渲染混在一起,导致无法复用或测试困难。比如在 React 中直接在 useEffect 里计算切片,或在 Vue 的 computed 中硬编码 pageSize —— 这会让逻辑耦合 UI,后续改每页显示数就得翻遍模板。
-
currentPage必须从 1 开始(用户感知页码),但数组索引从 0,所以起始索引是(currentPage - 1) * pageSize - 结束索引用
Math.min(start + pageSize, data.length),避免越界报错 - 不要用
splice原地修改原数组,用slice保证不可变性
前端分页要不要发请求?
取决于数据量。如果总数据不到 200 条,一次性拉取后前端分页更稳:没网络抖动、无 loading 状态管理、跳页响应快。这时候 fetch 只需执行一次,后续所有翻页都是纯内存操作。
一旦总条数上万,或用户可能只看前几页,就必须后端分页 —— 否则首屏加载慢、内存占用高、手机端易卡死。此时前端要传 page 和 limit 参数给接口,且必须校验后端返回的 total 字段来算总页数,不能靠前端猜。
立即学习“Java免费学习笔记(深入)”;
- 前端分页时,总页数 =
Math.ceil(data.length / pageSize) - 后端分页时,总页数 =
Math.ceil(response.total / pageSize),且需容错:若response.total缺失,降级为显示“下一页”按钮而非页码数字 - 别在 URL 上用
?page=abc这类非法值,parseInt后要检查是否为有效数字
点击页码按钮时如何避免重复触发?
用户手快连点「下一页」,可能触发多次 fetch 或多次 setState,造成状态错乱或请求堆积。关键不是防抖,而是加状态锁 + 请求取消机制。
对于原生 JS + fetch:用 AbortController 在发起新请求前 abort 上一个;对于 React,可在 useEffect 清理函数中 abort;Vue 3 的 onBeforeUnmount 同理。
- 维护一个
isLoading状态,按钮点击后立即设为true,禁用按钮,请求完成再设回false - 不要只禁用按钮却不阻断
onClick逻辑,否则用户右键新标签页打开链接仍会触发 - 如果用
async/await,确保try/catch包住整个流程,失败后也要重置isLoading
页码组件怎么处理“省略号”逻辑?
当总页数太多(比如 50 页),不能全铺开。标准做法是:始终显示第 1 页、最后 1 页、当前页及左右各 1~2 页,中间用 ... 隔开。这个逻辑容易写错边界,建议拆成独立函数 generatePageNumbers。
典型错误是把「当前页居中」当成固定规则,结果第 2 页时左边没空间,还强行留空;或总页数只有 5 页却仍画 ...。必须按实际页数动态判断。
- 当
totalPages ,直接显示 1 到totalPages - 否则:固定显示
1、...、currentPage-1、currentPage、currentPage+1、...、totalPages - 注意
currentPage-1不能小于 2,currentPage+1不能大于totalPages-1,否则替换为相邻真实页码
分页最麻烦的从来不是切数组,而是各种边界组合:首页 + 总数为 0、最后一页 + 用户手动输超限页码、后端返回空数组但 total 是 100……这些情况不提前想清楚,上线后第一波用户反馈就是分页按钮点不动或者显示 NaN。










