必须用 table.on('checkbox(filter)') 监听,filter 必须与 lay-filter 值严格一致;data.type === 'all' || !data.type 结合 data.checked 判断全选/全不选;禁止手动操作 dom,应调用 table.checkstatus() 获取状态。

必须用 table.on('checkbox(filter)') 监听,filter 要和 lay-filter 完全一致
直接给表头 checkbox 绑定 click 或 change 事件完全无效——Layui 渲染后的真实 <input type="checkbox"> 是隐藏的,UI 层由 <div class="layui-form-checkbox"> 模拟,你点的是 div,原生事件根本到不了 input。
<p>常见错误写法:<code>$('thead input[type="checkbox"]').on('click', ...) 或 document.querySelector('...').addEventListener('change', ...),这类绑定只对首次渲染前的 DOM 有效,分页、重载、展开子行后全部失效。
正确路径只有一条:table.on('checkbox(userTable)'),其中 userTable 必须和 table.render() 中配置的 lay-filter: "userTable" 字符串严格一致:大小写、空格、符号都不能差。
多个表格共用同一个 lay-filter 值会导致事件互相干扰,比如点 A 表格的全选框,B 表格的回调也执行了。
如何准确判断是“全选”还是“全不选”
data.type === 'all' 表示操作对象是表头全选框,但它的值在旧版 Layui(2.7.x 及更早)中可能是空字符串,不能单靠它做分支。
真正可靠的判断逻辑是:data.type === 'all' || !data.type,再结合 data.checked 的布尔值:
-
data.checked === true→ 用户点了“全选” -
data.checked === false→ 用户点了“全不选”
别依赖 data.value:全选框通常没设 value,data.value 是 undefined,拿它判断会出错。
如果表格启用了树形结构或子行展开,data.type 还可能是 'child',建议预留兼容分支:if (data.type === 'all' || data.type === 'child')。
监听到之后,千万别手动改 DOM
data.checked 是 Layui 已计算好的逻辑状态,不是原生 DOM 属性。你不需要、也不应该用 $().prop('checked', true) 去同步子项——这会导致 UI 和内部状态脱节,后续调用 table.checkStatus() 返回结果错乱。
真正要做的只有两件事:
- 实时统计当前页已选数量:调用
table.checkStatus('userTable').data.length - 跨页记住选中项:把
data.data.id(单选时)或遍历table.checkStatus('userTable').data收集所有已选 ID
如果你需要更新页面上某个统计 badge 的数字,直接读 table.checkStatus(...).data.length 就够了,不要自己维护计数器。
容易被忽略的细节:done 回调不是监听入口
有人误以为要在 table.render() 的 done 回调里手动绑定事件,这是错的。table.on('checkbox(...)') 是全局监听器,只要注册一次,就能捕获所有后续操作(包括分页切换后新渲染的行、键盘空格切换、点击表头等)。
done 回调只适合做一次性初始化动作,比如设置默认选中状态、调整列宽、显示提示信息等。把 checkbox 监听写在 done 里,不仅冗余,还可能导致重复绑定。
最常被忽略的耦合点,是多个表格共用同一 lay-filter 值;其次是监听回调里没做 data.type 兼容判断,导致旧版 Layui 下全选逻辑失效。











