table.on('checkbox(filter)')是唯一可靠入口,必须与lay-filter值严格一致;需区分全选/单选、避免手动改DOM、半选状态需原生设置并防渲染覆盖。
table.on('checkbox(filter)', callback) 是唯一可靠入口
直接给表格 checkbox 绑定 click 或 change 事件完全无效,因为 layui 渲染后的真实 dom 是隐藏的,ui 层是模拟出来的。必须走表格实例的内置事件系统,且 filter 必须和 table.render() 中的 lay-filter 值严格一致。
常见错误现象:
- 用
$('input[type="checkbox"]').on('click', ...)—— 只能捕获首次渲染前的 DOM,后续动态行、分页切换后全部失效 - 监听
form.on('checkbox(...)—— 这是表单级监听,对表格内部带lay-skin="primary"的复选框不生效 - filter 名写错或重复(比如多个表格共用
lay-filter="userTable")—— 一个勾选会触发所有表格的回调
正确写法示例:
table.render({
elem: '#userTable',
id: 'userTable',
lay-filter: 'userTable', // 注意这个值
cols: [[
{type: 'checkbox'},
{field: 'username', title: '用户名'}
]]
});
table.on('checkbox(userTable)', function(data) {
if (data.type === 'all') {
console.log('全选状态变更:', data.checked);
} else {
console.log('某行被操作:', data.data, data.checked);
}
});
区分全选和单选不能只看 data.type
data.type 在 Layui 2.8+ 是可靠的,但旧版可能为空字符串;更稳妥的方式是结合 DOM 属性判断,尤其当表格里混有自定义 checkbox 时。
推荐做法:
- 给全选框加
data-type="all"或固定name="tableAll",在回调里用data.elem.dataset.type === 'all'或data.elem.name === 'tableAll'判断 - 避免依赖
data.value,未设 value 的 checkbox 点击时data.value是undefined,容易误判 - 如果表格开启了多级展开或树形结构,
data.type可能为'child'或其他扩展类型,需预留兼容分支
监听到状态变化后,别手动改 DOM
data.checked 是事件触发时的逻辑状态,不是原生 DOM 的 checked 属性。你不需要、也不应该用 $(...).prop('checked', true) 去同步子项 —— 表格内部状态已由 Layui 自动维护。
真正需要你干预的只有两类场景:
- 需要实时统计当前页已选数量:调用
table.checkStatus('userTable').data.length,别遍历 DOM - 需要跨页记住选中状态:把
data.data.id存进数组,配合table.cache手动比对,Layui 不自动跨页保持 - 反选逻辑里,别先全清再重设 —— 直接循环子项 DOM,执行
item.checked = !item.checked,然后统一form.render('checkbox')
半选状态(indeterminate)得自己画
Layui 原生不支持全选框的半选样式,即部分子项勾选时显示“—”。这个状态必须手动设置并绕过 Layui 渲染控制。
关键点:
- 用原生 DOM 设置:
document.getElementById('checkAll').indeterminate = true - 设置后要补 CSS 修复样式冲突,例如加
.layui-form-checkbox[indeterminate] .layui-icon { display: none; }隐藏默认对勾 - 别在
table.on('checkbox(...)')回调里直接设indeterminate后就结束 —— Layui 下次form.render()会把它清掉,得在每次状态更新后重新设置
复杂点不在逻辑,而在时机:DOM 存在、Layui 渲染节奏、你手动干预的边界,三者错一个,indeterminate 就闪一下就消失。











