done回调是数据加载完毕的唯一可靠信号,它在HTTP响应成功、res校验合法、分页参数计算完成且tbody插入DOM后触发,但不保证视觉样式就绪或DOM完全渲染。

done回调就是数据加载完毕的唯一可靠信号
layui表格没有“渲染完成”或“DOM就绪”的独立钩子,done是框架明确提供的、**唯一能确认原始响应数据已接收、解析并准备就绪**的时机。它不保证所有视觉样式或滚动条补丁已注入,但足以确认 res 可用、分页参数(curr, count)已生效、当前页数据已进入内存。
为什么不能用 table.render() 返回值或 setTimeout 判断
table.render() 本身是同步调用,返回的是配置对象,不是 Promise,也不阻塞后续代码;直接在它后面写 document.querySelector('.layui-table tbody tr') 大概率查不到——因为 DOM 插入是异步的,且可能被后续 scroll 补丁覆盖。
- 用
setTimeout(() => {}, 0)或Promise.resolve().then()无法替代done:它们只等 JS 执行队列清空,不感知 layui 内部的数据绑定与分页逻辑 - 监听
table.on('pull', 'filter')或table.on('sort', 'filter')是事件响应,不是加载状态判断依据 - 检查
layui.table.cache['id']是否存在?不可靠——cache 在done前就可能被预设,但数据未必来自本次请求
done 回调触发的准确条件
done 在以下全部满足时触发:
- HTTP 请求成功返回(或本地
data已传入) -
res被校验为合法对象(含data数组和可选的count) - 当前页码
curr和总条数count已计算完成(即使后端没返回count,Layui 也会按res.data.length估算) - 表格主体
<tbody> 已插入 DOM,且每行 <code><tr> 的 <code>data-index属性已写入(注意:这个属性仅用于内部定位,不建议依赖)只要配置了
url或data,done就一定会执行一次;开启分页后,每次翻页、搜索、重载也都会再次触发。容易误判的典型场景
常见错误是把“数据加载完毕”和“用户可见内容稳定”混为一谈:
- 虚拟滚动开启(
limit > 100)时,done中遍历document.querySelectorAll('tbody tr')只拿到可视区域行,但res.data是整页数据——别用 DOM 数量反推是否加载完 - 用了
response配置自定义字段名(如statusName: 'code'),但done的res仍是原始响应体,未经过 response 映射——校验逻辑要基于原始结构写 - 表格容器本身被动态
display: none隐藏,done仍会触发,但后续 DOM 操作(如getBoundingClientRect())可能返回 0 —— 此时需额外监听容器可见性
真正需要“DOM 完全就绪”的操作(比如精确测量行高、绑定原生事件),得在
done内再套一层setTimeout(() => {}, 0),让浏览器有机会完成 layout。 - 虚拟滚动开启(


















