layui分页接口必须返回code、msg、count、data四个顶层字段,其中code必须为0,count为总记录数,data为纯数组;后端需手动构造该结构,不能直接返回thinkphp分页对象。

layui分页接口必须返回什么字段
Layui 的 table.render() 或 laypage.render() 不接受 ThinkPHP 默认分页对象(如 $list->render() 或 $list->toArray()),直接传会丢 count、当前页偏移逻辑失效。后端必须返回固定 JSON 结构,且字段名不能错:
-
code:必须为0(非 0 被视为失败,msg会弹出提示) -
msg:可为空字符串"",不能省略或为null -
count:总记录数,必须用$list->total(),不是count($list->items())(那是当前页条数) -
data:纯数组,元素为每条数据对象;必须用$list->items(),不用$list->all()(后者含分页元信息,会干扰渲染)
ThinkPHP 后端怎么手动构造这个格式
TP5/6 中不能依赖 paginate() 的默认输出,得拆开算总数 + 当前页数据。常见错误是把 input('page') 和 input('limit') 拿来直接算 offset 却没校验范围,导致越界或空页。
- 先取参数:
$page = max(1, (int)input('page', 1))、$limit = max(1, (int)input('limit', 10)) - 查总数:
$total = Db::name('user')->where($where)->count()(别用模型的paginate()->total()再查一遍,浪费) - 查当前页数据:
$data = Db::name('user')->where($where)->page($page, $limit)->select()->toArray() - 拼响应:
return json(['code'=>0, 'msg'=>'', 'count'=>$total, 'data'=>$data])
注意:TP 的 page($page, $limit) 是底层封装,比手动算 offset = ($page-1)*$limit 更安全,自动处理边界。
前端 table.render() 的 page 配置容易写错的位置
很多人把 limit 写在顶层配置里,Layui 完全忽略,静默 fallback 到默认 30 条 —— 这是最常被卡住的地方。
- ❌ 错误写法:
table.render({ elem: '#demo', url: '/api/list', limit: 20, page: true })(limit在外层,无效) - ✅ 正确写法:
table.render({ elem: '#demo', url: '/api/list', page: { limit: 20 } })(limit必须嵌在page对象内) -
page: { limit: 20, curr: input('page', 1) }中的curr可选,但服务端若需首次渲染指定页码,就得传 - 如果用了
limits: [10,20,50],limit值必须是其中之一,否则分页器初始化失败
为什么 parseData 有时看起来“没生效”
parseData 是前端接管原始响应、重组成 layui 所需结构的钩子,但它只在 url 配置存在时触发;如果误配成 data(本地数据模式),它根本不会执行。
- 确认你用的是
url: '/api/list',不是data: [...] -
parseData函数里,this.page.curr和this.limit是当前请求上下文值,别用全局变量覆盖 - 常见调试方式:
console.log('res:', res, 'curr:', this.page.curr, 'limit:', this.limit) - 若想前端全量加载再分页(小数据量场景),
res.data应是全部数据数组,然后用slice((curr-1)*limit, curr*limit)截取
真正难调的点不在格式本身,而在前后端参数名是否对齐 —— 比如前端发 ?page=2&size=15,后端却只读 input('limit'),那就永远拿不到 size。参数映射必须显式声明:request: { pageName: 'page', limitName: 'size' }。











