Layui table翻页丢失复选框状态是因为每次重绘DOM且不维护跨页选中记忆,需用两个数组手动管理:temp_all_list存所有已选项ID,temp_table_list存当前页数据,并在done回调中匹配回填LAY_CHECKED字段及样式。
为什么默认切换页码后复选框状态会丢失
layui 的 table.render 每次翻页都会重新请求数据、重绘 dom,res.data 是全新数组,之前勾选的 lay-checked 样式和 checked 属性不会自动带过去——它不维护“选中状态”的跨页映射,只管当前页渲染。
你看到的“勾选消失”,本质是:DOM 被重建了,但没人告诉新 DOM “这些行之前被点过”。Layui 本身没做这层记忆,得自己补。
-
table.checkStatus('id')只能拿到当前页已勾选的数据,翻页后就清空了 -
res.data里没有LAY_CHECKED字段,除非你手动塞进去 - 直接操作
$('input[type="checkbox"]').prop('checked', true)不够——还得同步加layui-form-checked类,否则样式不生效
用两个全局变量管理选中状态最稳
不需要改源码、不依赖插件,靠两个数组就能闭环:一个存所有已选中项(按唯一 ID),一个存当前页原始数据。关键在 done 回调里做匹配回填。
示例核心逻辑:
var temp_all_list = []; // 存所有已选中的完整对象(建议用 id 做 key 更安全)
var temp_table_list = []; // 存当前页全部数据,供 done 中遍历比对
<p>table.render({
elem: '#user_table',
id: 'user_table',
url: 'personnel/select',
page: true,
cols: [[{type: 'checkbox'}, /<em> 其他列 </em>/]],
done: function(res, curr, count) {
temp_table_list = res.data;
// 遍历当前页每条数据,看是否在 temp_all_list 中存在
temp_table_list.forEach(function(row) {
var found = temp_all_list.some(item => item.id === row.id);
if (found) {
row.LAY_CHECKED = 'true'; // 关键:必须设这个字段
var index = row.LAY_TABLE_INDEX;
$('.layui-table tr[data-index="' + index + '"] input[type="checkbox"]')
.prop('checked', true)
.next().addClass('layui-form-checked');
}
});
// 同步全选框状态(可选)
var checkStatus = table.checkStatus('user_table');
var $thCheckbox = $('.layui-table th[data-field="0"] input[type="checkbox"]');
$thCheckbox.prop('checked', checkStatus.isAll).next().toggleClass('layui-form-checked', checkStatus.isAll);
}
});- 选中事件监听必须绑定在
form.on('checkbox(*)', ...),不能只靠 click —— layui 的 checkbox 是封装过的表单元素 - 存
temp_all_list时,别 push 原始row对象(含 LAY_TABLE_INDEX 等临时字段),建议只存 {id, ...} 干净结构 - 如果后端返回的主键不是
id,比如是eno,那所有item.id === row.id都得换成item.eno === row.eno
监听 checkbox 事件时容易漏掉全选/反选逻辑
只监听单个 checkbox 点击,不处理表头全选框,会导致“点了全选 → 切页 → 再回来只剩部分勾选”——因为全选动作没记录到 temp_all_list 中。
正确做法是统一收口到一个函数:
form.on('checkbox(user_table)', function(obj){
var data = obj.elem.checked ? obj.data : null;
if (obj.type === 'all') {
// 全选 or 取消全选
if (obj.checked) {
// 把当前页所有数据 id 加入 temp_all_list(去重)
temp_table_list.forEach(function(row) {
if (!temp_all_list.some(it => it.id === row.id)) {
temp_all_list.push({id: row.id});
}
});
} else {
// 清除当前页所有 id
temp_table_list.forEach(function(row) {
var idx = temp_all_list.findIndex(it => it.id === row.id);
if (idx > -1) temp_all_list.splice(idx, 1);
});
}
} else {
// 单选
if (obj.checked) {
if (!temp_all_list.some(it => it.id === data.id)) {
temp_all_list.push({id: data.id});
}
} else {
var idx = temp_all_list.findIndex(it => it.id === data.id);
if (idx > -1) temp_all_list.splice(idx, 1);
}
}
});- 务必判断
obj.type === 'all',这是 layui 区分表头全选事件的关键字段 - 不要用
temp_all_list = [...new Set(...)]去重——Set 无法识别对象相等,得手动 findIndex - 如果表格支持搜索或筛选,
temp_table_list必须随搜索结果更新,否则比对会失效
radio 跨页保持选中要额外同步 cache
如果你表格里混用了 type: 'radio',光改 res.data 和 DOM 不够。Layui 内部用 table.cache['id'] 缓存原始数据,翻页时读的是 cache,不是你改过的 res.data。
所以 radio 场景下,除了更新 DOM 和 temp_all_list,还必须手动同步 cache:
form.on('radio(user_table)', function(obj){
var id = obj.value; // 假设 value 是唯一标识
// 更新你的选中缓存
temp_radio_selected = id;
// 同步到 table.cache,确保翻页后仍可用
var cache = table.cache['user_table'];
if (cache && cache.length) {
cache.forEach(function(row) {
row.LAY_RADIO_CHECKED = (row.id == id);
});
}
});- 这个坑只在 radio 出现,checkbox 不需要动 cache
-
table.cache是私有属性,但 layui 官方文档也明确写了可读写,生产环境用没问题 - 如果 radio 选项来自后端枚举,建议把选中值存在 localStorage 或 vuex,避免刷新丢失
实际项目里最常被忽略的,是搜索重载后没清空或重置 temp_table_list,导致 done 里比对的还是上一次分页的数据。只要记住:任何导致 res.data 变更的操作(搜索、筛选、排序),都要同步更新 temp_table_list。

















