第 9 章 · Layui table 数据表格与分页
本章目标:掌握 table.render 的 cols、page、toolbar 配置;理解服务端分页的 request/response/parseData 与 where 搜索条件;实现行工具栏编辑/删除、checkbox 批量操作;在 admin-demo 完成订单列表 table 完整示例(对接 Mock API)。
学时建议:4 小时(含 80 分钟跟练)
前置:ch07 布局、ch08 表单搜索;ch04 jQuery Ajax。
9.1 table 模块概览
Layui table 将大数据列表抽象为:
table.render({ elem, url, cols, page, ... })
│
▼
自动 Ajax 拉取 + 分页 + 排序(可选)
│
▼
渲染 HTML 表格 + 绑定行事件 table.on('tool')
行业常见 Layui 商户后台中,product-list.html、sku-list.html、order-list.html 等均采用同一模式,是标准列表范式。
| 能力 | API |
|---|---|
| 初始化 | table.render(options) |
| 重载数据 | table.reload(id, options) |
| 行按钮 | table.on('tool(filter)', fn) |
| 头工具栏 | table.on('toolbar(filter)', fn) |
| 复选 | type: 'checkbox' 列 + checkStatus |
9.2 最小 table 示例
<table id="demoTable" lay-filter="demoTable"></table>
<script type="text/html" id="rowBar">
<a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a>
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</a>
</script>
layui.use('table', function () {
var table = layui.table;
table.render({
elem: '#demoTable',
url: '/api/items',
page: true,
cols: [[
{ type: 'checkbox', fixed: 'left' },
{ field: 'id', title: 'ID', width: 80 },
{ field: 'name', title: '名称' },
{ fixed: 'right', title: '操作', toolbar: '#rowBar', width: 150 }
]]
});
});
lay-filter="demoTable" 与 table.on('tool(demoTable)') 的 filter 一致。
9.3 cols 列配置详解
cols: [[
{ type: 'numbers', title: '序号', width: 60 },
{ type: 'checkbox', fixed: 'left' },
{ field: 'order_no', title: '订单号', width: 180, sort: true },
{ field: 'amount', title: '金额', width: 100, align: 'right',
templet: function (d) {
return '¥' + parseFloat(d.amount).toFixed(2);
}
},
{ field: 'status', title: '状态', width: 100,
templet: '#statusTpl' // 引用 script 模板
},
{ fixed: 'right', title: '操作', toolbar: '#rowBar', width: 160 }
]]
| 属性 | 说明 |
|---|---|
field | 数据字段名 |
title | 表头文字 |
width / minWidth | 列宽 |
fixed | left / right 固定列 |
sort | 前端排序(服务端排序需传参,见 9.5) |
templet | 函数或 #id 模板自定义单元格 |
hide | 默认隐藏列 |
type | checkbox / radio / numbers |
状态列模板:
<script type="text/html" id="statusTpl">
{{# if(d.status === 'paid'){ }}
<span class="layui-badge layui-bg-green">已支付</span>
{{# } else if(d.status === 'pending'){ }}
<span class="layui-badge layui-bg-orange">待支付</span>
{{# } else { }}
<span class="layui-badge">已关闭</span>
{{# } }}
</script>
使用 Layui 内置模板语法 {{# }},便于非程序员修改展示逻辑。
9.4 分页 page 配置
page: {
layout: ['limit', 'count', 'prev', 'page', 'next', 'skip'],
curr: 1,
limit: 10,
limits: [10, 20, 50, 100],
groups: 5,
first: '首页',
last: '末页'
}
| 参数 | 默认 | 说明 |
|---|---|---|
pageName | page | 请求页码字段名(request 内改) |
limitName | limit | 每页条数字段名 |
curr | 1 | 初始页 |
limit | 10 | 每页条数 |
仅前端分页:设 page: true 且一次返回全部数据(小数据量演示用)。生产与 admin-demo 均用服务端分页。
9.5 服务端分页:request / response / parseData
后端返回格式各异,Layui 用 request + response 映射;若不匹配再用 parseData 转换。
9.5.1 行业常见 POST 分页风格
table.render({
elem: '#productTable',
url: '/api/products',
method: 'post',
request: {
pageName: 'page',
limitName: 'limit'
},
response: {
statusName: 'code',
statusCode: 0,
msgName: 'msg',
countName: 'total',
dataName: 'list'
},
page: true,
limit: 10
});
Ajax 请求体示例:{ page: 2, limit: 10 }
期望响应:
{
"code": 0,
"msg": "ok",
"total": 156,
"list": [ { "id": 1, "name": "..." } ]
}
9.5.2 admin-demo Mock API 风格
response: {
statusName: 'code',
statusCode: 0,
countName: 'count',
dataName: 'list'
},
parseData: function (res) {
return {
code: res.code,
msg: res.message,
count: res.data.total,
data: res.data.list
};
}
parseData 在 response 映射之后执行,适合一层嵌套 { data: { total, list } }。
9.5.3 where 搜索条件
table.reload('orderTable', {
where: {
order_no: 'ORD2026',
status: 'paid',
date_range: '2026-08-01,2026-08-19'
},
page: { curr: 1 } // 搜索时重置到第一页
});
where 与分页参数一并提交;ch08 搜索表单 submit 里组装 field 后 reload。