分页数据应由后端按 page 和 limit 返回,前端仅传参、渲染及管理状态;page 通常从 1 开始,limit 建议固定;响应需含 total 以计算总页数;优先使用成熟 UI 库分页组件,手写需处理边界;点击分页适合需跳转、SEO 场景,无限滚动适用于内容流;前端本地分页仅限小量静态数据。

分页数据怎么从后端拿:用 page 和 limit 控制
绝大多数分页不是前端“算出来”的,而是靠后端按页返回数据。前端只负责传参数、渲染、翻页状态。关键参数通常是 page(当前页码,一般从 1 开始)和 limit(每页条数)。后端根据这两个值查对应区间的数据。
常见错误是前端把 page 当成从 0 开始——比如第一页传 page=0,结果后端没匹配上,返回空数组或报错。务必确认接口文档约定。
-
page通常为正整数,1表示第一页 -
limit建议固定(如10或20),避免用户随意输导致性能抖动 - 请求时带上加载中状态,防止重复点击“下一页”发多次请求
- 后端响应里最好包含
total(总条数)、page、limit,方便前端算总页数:Math.ceil(total / limit)
前端渲染分页控件:手写还是用库?
纯手写分页按钮逻辑不难,但边界情况多:比如只有 1 页要不要显示?页码太多要不要省略(1 ... 5 6 7 ... 100)?移动端要不要折叠?这些细节容易反复踩坑。
如果项目已用 React 或 Vue,优先选生态内成熟组件,比如 Ant Design 的 Pagination 或 Element Plus 的 el-pagination。它们默认处理了禁用态、键盘导航、屏幕阅读器支持等。
立即学习“Java免费学习笔记(深入)”;
若必须手写,核心是生成页码数组:
function generatePageNumbers(current, total, siblingCount = 1) {
const pages = [];
const totalPageCount = Math.ceil(total);
if (totalPageCount <= 6) {
for (let i = 1; i <= totalPageCount; i++) pages.push(i);
} else {
const leftSiblingIndex = Math.max(2, current - siblingCount);
const rightSiblingIndex = Math.min(totalPageCount - 1, current + siblingCount);
pages.push(1);
if (leftSiblingIndex > 2) pages.push('...');
for (let i = leftSiblingIndex; i <= rightSiblingIndex; i++) pages.push(i);
if (rightSiblingIndex < totalPageCount - 1) pages.push('...');
pages.push(totalPageCount);}
return pages;
}
注意:这个函数返回的是要显示的页码项(含 '...' 字符串),不是原始数据索引,别直接拿去当 page 参数发请求。
无限滚动 vs 点击分页:什么时候该选哪个?
“分页”不等于必须点数字按钮。两种主流交互方式适用场景差异明显:
-
点击分页(Page-based):适合需要跳转到指定页、支持 URL 分享、数据总量明确(如后台管理列表)、SEO 敏感的场景。URL 可带
?page=3&limit=10,刷新不丢状态 - 无限滚动(Infinite scroll):适合内容流型产品(如信息流、商品瀑布流),用户预期是“一直往下看”。但缺点是无法跳到中间页、浏览器前进/后退失效、不利于 SEO、内存占用随滚动持续增加
别为了“酷”强行用无限滚动。电商商品搜索结果页如果不用传统分页,用户想找第 47 页的某款老型号,基本找不到。
前端本地分页:什么情况下能用,有什么代价?
只有当全部数据一次性加载完成(比如 100 条以内),且确定不会增删改,才考虑前端分页。典型场景:配置项列表、静态帮助文档目录。
否则极易出问题:
- 数据量稍大(如 5000 条)时,JSON 解析+数组切片会卡顿,尤其低端手机
- 用户在第 5 页,后台新增了数据,前端无感知,翻页就“漏掉”新条目
- 搜索过滤后又点分页,逻辑容易混乱(是先 filter 再分页?还是分页后再 filter?)
真要用,核心就是 slice:
const allData = [/* 一整个数组 */]; const currentPage = 3; const limit = 10; const startIndex = (currentPage - 1) * limit; const paginatedData = allData.slice(startIndex, startIndex + limit);
但请再确认一遍:你真的不需要服务端分页吗?大多数所谓“前端分页需求”,其实是没跟后端对齐接口设计。










