必须让无权限按钮根本不生成,后端需为每行数据返回严格布尔型权限字段(如canedit、candelete),字段名大小写敏感且不能为字符串;前端模板用{{# if(d.canedit) { }}控制渲染,整列隐藏需结合hide参数与权限判断。
不能靠 defaulttoolbar 控制显隐,也不能用 $().hide() 临时隐藏——按钮 dom 还在,权限就形同虚设;必须让没权限的按钮压根不生成。
后端必须每行返回布尔型权限字段(如 canEdit、canDelete)
前端模板里写的 {{# if(d.canEdit) { }},只认 d 对象里的字段。如果后端返回的数据长这样:
{ "id": 1, "name": "张三", "status": "active" }
那 d.canEdit 就是 undefined,条件永远不成立,按钮永远不会出现。
- 后端需确保每条数据都带权限字段,且类型为
true/false(不是字符串"true") - 字段名大小写必须完全一致:
canedit≠canEdit - 避免在模板里写
{{# if(d.role === 'admin') { }}—— 角色判断应由后端完成并转为明确布尔值
toolbar 模板里用 {{# if() { }} 控制按钮渲染
Layui 的 toolbar 模板是服务端返回数据后、客户端执行的 JS 模板,不是 HTML 字符串拼接。只要条件不满足,对应按钮标签就不会出现在 DOM 中。
- 模板定义要写在
<script type="text/html"></script>里,id和cols中toolbar属性值保持一致 - 示例模板:
<script type="text/html" id="tableBar">{{# if(d.canEdit) { }}<button class="layui-btn layui-btn-xs" lay-event="edit">编辑{{# } }}{{# if(d.canDelete) { }}<button class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除{{# } }}</script> - 别在按钮上加
disabled来“假装禁用”——没权限就该彻底不渲染
权限字段是字符串 "false" 会导致按钮误显示
这是线上最隐蔽的权限漏洞:后端 JSON 序列化时若把布尔值转成字符串(比如 Java 的 String.valueOf(false)),JS 模板里 {{# if(d.canDelete) { }} 会把非空字符串当真值处理,按钮照常渲染。
- 检查浏览器控制台打印的
table.cache数据,确认canDelete是false还是"false" - 后端应直接输出 JSON 布尔字面量:
"canDelete": false,而非"canDelete": "false" - 前端临时补救(不推荐):
{{# if(d.canDelete === true) { }},但治标不治本
操作列整列隐藏需结合 hide 参数和权限判断
如果某类用户连“操作”这一列都不该看到(比如只读角色),就不能只靠模板控制按钮,而要让整列消失。
- 先确定是否有任意一行能显示按钮:
const hasAnyAction = data.some(row => row.canEdit || row.canDelete) - 把这个结果传给
cols配置:{ align: 'center', title: '操作', toolbar: '#tableBar', hide: !hasAnyAction } - 注意:
hide是初始化参数,不能在done回调里动态改——改了也不会重绘列头 - 如果权限异步加载,必须等权限返回后再调用
table.render(),否则hide判断会失效
真正难的不是写几行 {{# if() { }},而是让后端稳定输出结构一致的布尔字段,并确保前后端字段名、类型、生命周期完全对齐。一旦其中一环错位,按钮就会“该藏不藏”或“该显不显”。











