必须开启服务端分页,否则Layui会全量渲染DOM导致卡顿;后端需支持page/limit参数并返回count和data;前端配置page:true及对应request/response字段;设height启用虚拟滚动;禁用templet函数、totalRow等非必要功能。
必须开服务端分页,否则前端扛不住
只要原始数据超过 500 行,且 page: false 或 page: { limit: 1000 },layui 就会把全量数据转成 <tr><td> 插进 dom —— 你只看第 1 页,它也渲染全部。浏览器重排压力直接拉满,滚动卡、点 checkbox 延迟、甚至输入框失焦。
<p>后端接口必须支持 <code>page 和 limit 参数(如 ?page=2&limit=30),返回结构含 count 字段和当前页的 data 数组。前端配置里:page: true,request: { pageName: 'page', limitName: 'limit' },response: { countName: 'count', dataName: 'data' }。
- 别信“我后端查得快”,快也没用,Layui 还是要 render 全量 DOM
- 如果后端没法改,宁可本地切数据(
data: res.data.slice((page-1)*limit, page*limit)),也别留page: { limit: 9999 } -
totalRow: true会遍历整页数据求和,大数据下禁用
设 height 触发虚拟滚动,不然万级数据直接卡死
Layui 的虚拟滚动不是默认开启的,必须显式设置 height(比如 height: 500 或 height: 'full-200')。没这个值,哪怕你有 1 万行数据,它照样全量生成 DOM 节点,主线程 block 到浏览器弹出“页面无响应”。
真实压测中,加了 height 后,1w 行表格首次渲染从 4.2s 降到 320ms,滚动帧率从 8fps 提升到 58fps。
- 高度不能是
auto或未设置,必须是具体数值或计算式 - IE11 下还需给
<table> 加 <code>style="table-layout: fixed;",否则列宽反复重算 - 配合
cellMinWidth: 80(别用默认 60),减少 resize 时的 layout thrashing - 避免在 templet 里调
$.ajax、JSON.parse、复杂正则匹配 - 状态徽章、按钮图标等静态内容,优先用
toolbar配置或templet: '#tpl-id'引用 script 模板 - 列内容过长时,用
templet截断(return d.title?.substring(0,20)+'...'),别依赖自动换行撑高行高 - 不用合计行?删掉
totalRow: true - 不需要列拖拽?去掉
unresize: false(默认就是 true) - 骨架屏比 loading 动画更稳:用
before和done控制 CSS 类,确保尺寸一致
templet 函数是性能黑洞,能不用就不用
每个 templet 函数在渲染每行时都会执行一次。1000 行就是 1000 次 JS 执行 + 作用域创建 + 字符串拼接 —— 这比纯模板快不了多少,还绕不开 V8 优化。
把 templet: function(d) { return d.time ? new Date(d.time).toLocaleString() : '-'; } 改成字符串模板:templet: '{{ d.time ? utils.toDate(d.time) : "-" }}'(前提是 utils.toDate 是全局函数),或更干脆:后端直接返回格式化后的字符串字段。
关掉所有不必要功能,省下的都是渲染时间
toolbar、defaultToolbar、skin: 'line'、loading: true 这些看着“完整”的配置,实际都在初始化阶段做额外遍历或 DOM 注入。实测禁用后,首屏渲染快 30%+。
尤其注意:toolbar: '' 或 toolbar: true 并不等于关闭 —— 它们仍会初始化工具栏逻辑。真正关闭是删掉整个 toolbar 字段。
count 必须准确,且不能为 null 或 0(Layui 分页栏会消失);height 必须设,哪怕只是 400;templet 函数里别写 console.log —— 万次输出本身就会拖慢渲染。**











