必须在列配置中用templet函数或模板脚本内联判断行数据字段,不能靠外部JS操作DOM;禁用只是UI层面的视觉反馈,事件回调里必须二次校验状态,否则用户删掉layui-btn-disabled类就能绕过;toolbar是全局渲染、不绑定单行上下文,拿不到d对象,只适合“导出全部”等不依赖行数据的操作。
必须在列配置中用 templet 函数或模板脚本内联判断行数据字段,不能靠外部 js 操作 dom;禁用只是 ui 层面的视觉反馈,事件回调里必须二次校验状态,否则用户删掉 layui-btn-disabled 类就能绕过。
为什么 toolbar 不适合做状态禁用
toolbar 是全局渲染的,不绑定单行上下文,d 在里面拿不到当前行数据。很多人写 { fixed: 'right', toolbar: '#barDemo' },再在 #barDemo 模板里写 {{d.status}},结果全是 undefined —— 因为 toolbar 模板压根不传 d。
- 只有列级
templet(函数或 script 模板)能稳定拿到d对象 - toolbar 适合放“全表操作”,比如“导出全部”“刷新列表”这类不依赖行数据的按钮
- 如果硬要用 toolbar,得配合
table.cache手动查索引找数据,但分页/排序后索引会变,极易出错
templet 中怎么写条件禁用逻辑
直接在列定义里写函数最轻量,也最容易调试:
{ field: 'operate', title: '操作', templet: function(d) {
return d.status === 'active'
? '<button class="layui-btn layui-btn-xs" lay-event="edit">编辑</button>'
: '<button class="layui-btn layui-btn-xs layui-btn-disabled">编辑</button>';
} }
- 用严格相等
===判断枚举值,比如'active'/'closed',避免==或!=漏掉undefined、null等边界情况 - 禁用按钮不要加
lay-event,Layui 会忽略它;只给可交互按钮加 - 别写成
if (d.status !== 'closed')这种反向逻辑,后期加新状态(如'archived')容易漏判
事件回调里必须二次校验状态
用户可能用 DevTools 删除 layui-btn-disabled 类,或者直接调用 obj.tr.querySelector('[lay-event="edit"]').click(),所以仅靠模板禁用是无效防线。
- 所有
table.on('tool(test)', ...)回调开头都加判断:if (obj.data.status !== 'active') { layer.msg('状态不可编辑'); return; } - 不要用
$(obj.tr).find('button')去读按钮的 disabled 属性——DOM 可能已被重载,且这个属性根本没参与事件触发逻辑 - 如果状态判断复杂(比如要叠加用户角色),把校验逻辑抽成独立函数,确保每次调用都基于
obj.data最新值
表格重载后状态丢失怎么办
table.reload() 会清空整个 <tbody> 并重建,所有手动加的 class、disabled 属性都会消失。Templet 是唯一能随数据自动重建状态的方式,但前提是模板 HTML 必须在 table.render() 前就存在于 DOM 中。
- script 模板要写在
<body>内、table.render()调用之前,不能动态append进去 - 不要在
done回调里用$('button').attr('disabled', ...)补救——重载后这些操作全失效 - 如果状态来自服务端异步计算(比如权限接口返回是否可编辑),得把结果作为字段塞进原始数据,让
d直接可用
真正容易被忽略的是:模板里写了禁用,事件里没二次校验,等于没设防;而模板本身如果没在 render 前就挂载好,reload 后连禁用样式都不会出现。


















