layui.table 默认不记住跨页选中状态,因其翻页时重绘DOM、丢弃原选中标识,且未绑定主键维护已选集合;需用id缓存selectedIds,并在done回调中同步row.LAY_CHECKED与checkbox状态。
为什么 layui.table 默认不记住跨页选中状态
因为 layui 的 table.render 每次翻页都会重新请求数据、重绘 dom,res.data 是全新数组,之前勾选的 obj.lay_checked 和 checkbox 的 checked 属性全被丢弃。它不自动维护“已选集合”,也不把选中状态和数据主键绑定 —— 所以你下一页再回来,就只剩空 checkboxes。
核心做法:用主键缓存选中项,done 里手动回填
关键不是操作 DOM,而是让 layui 内部识别哪些行该被“认为已选”。必须同时做两件事:
① 把用户点过的数据(建议用唯一字段如 id)存进一个全局数组,比如 selectedIds = [];
② 在 done 回调里,遍历当前页 res.data,对每个匹配 id 的项设置 row.LAY_CHECKED = true,并触发真实 checkbox 的勾选。
常见错误现象:
• 只改了 DOM 的 checked 属性,但没设 row.LAY_CHECKED → table.checkStatus('xxx').data 拿不到选中数据
• 用 index 或 LAY_TABLE_INDEX 当标识 → 翻页后 index 重排,完全错位
• 没在 done 里处理全选框状态 → 表头 checkbox 显示未全选,哪怕当前页所有数据都已在 selectedIds 里
table.on('checkbox(xxx)') 事件里该写什么
监听复选框变化时,只负责增删 selectedIds,别碰 DOM 或 table 实例。layui 已经帮你处理了单行勾选/取消的视觉更新,你只需同步业务状态:
- 勾选时:
if (obj.checked) { selectedIds.push(obj.data.id); } - 取消时:
if (!obj.checked) { selectedIds = selectedIds.filter(id => id !== obj.data.id); } - 全选/反选时:
obj.type === 'all'分支里,用res.data.map(d => d.id)批量操作,别用obj.data(它只含当前页)
注意:不要在 checkbox 监听里调 table.checkStatus 或尝试重绘表格 —— 这会引发重复渲染或状态冲突。
全选框状态怎么自动同步
全选框是否打钩,取决于当前页所有数据是否都在 selectedIds 中。这个判断必须放在 done 里做,不能靠监听事件推导:
const currPageIds = res.data.map(d => d.id);<br>const isAllCurrSelected = currPageIds.every(id => selectedIds.includes(id));<br>$('.layui-table th[data-field="0"] input[type="checkbox"]').prop('checked', isAllCurrSelected).next().toggleClass('layui-form-checked', isAllCurrSelected);
容易踩的坑:
• 忘记用 toggleClass 或手动加 class → 表面勾了,但样式没变
• 把 data-field="0" 写成其他值 → 如果你第一列不是 checkbox(比如加了 fixed 或 toolbar),得按实际列序号调整
• 在非 done 场景里强行读取当前页数据 → table.cache 未必及时更新,不可靠
最麻烦的其实是去重和性能:如果用户反复翻页又全选,selectedIds 可能堆积大量重复 id。上线前务必加一层 [...new Set(selectedIds)] 去重,尤其当后端返回数据没严格保证主键唯一时。










