templet 必须是函数,不能写死模板字符串;需根据 d.status 等字段用 if/else 直接返回 HTML 字符串,按钮必须带 lay-event 属性,fixed 列要设 width,空数据需先判空防护。
templet 必须是函数,不能写死模板字符串
静态模板里用 {{ d.status }} 做简单替换,根本跑不了 if/else 逻辑。layui 的模板引擎 laytpl 不支持在插值语法里执行条件分支,只做单层变量替换。一旦需要“状态为 draft 显示编辑,published 显示下架+禁用”,就必须把 templet 写成函数。
常见翻车点:
- 把
templet: '<button>{{ d.status }}</button>'当成万能解——它连字符串比较都做不到 - 在函数里调用
laytpl.render()或拼 DOM 元素——多此一举,返回纯 HTML 字符串就行 - 在
templet里发 AJAX 请求或改全局状态——这违背渲染函数的单一职责,容易引发竞态和 UI 不同步
根据 d.status 等字段写 if/else 分支,直接返回 HTML 字符串
函数形参 d 就是当前行原始数据对象,所有字段都可直接访问。别绕弯,就用原生 JS 判断 + 字符串拼接。
示例(注意引号嵌套和空格):
templet: function(d) {
if (d.status === 'draft') {
return '<button class="layui-btn layui-btn-xs" lay-event="edit">编辑</button>';
} else if (d.status === 'published') {
return '<button class="layui-btn layui-btn-xs" lay-event="unpublish">下架</button>' +
'<button class="layui-btn layui-btn-xs layui-btn-danger" lay-event="delete">删除</button>';
} else if (d.status === 'archived') {
return '<span class="layui-badge-rim">已归档</span>';
}
return '<span class="layui-text">--</span>';
}
关键提醒:
- 按钮必须带
lay-event属性,否则table.on('tool(filter)')监听不到 - 避免在字符串里写
onclick="",会和 Layui 的事件委托冲突 - 如果字段可能为空(比如
d.status === undefined),先判空再比较,不然===会失效
toolbar 和 event 属性完全替代不了 templet
toolbar 是整张表共用的顶部/右侧工具栏,它不感知某一行的状态;event 属性在新版 Layui(2.8+)里已被废弃,写了也不触发。有人试图把所有按钮都塞进 templet 字符串,再靠 table.on 里一堆 if (d.status === 'xxx') 控制点击行为——这等于把渲染逻辑和业务逻辑搅在一起,DOM 节点多、维护成本高、状态更新后极易漏掉按钮显隐同步。
真正干净的做法就一条:按钮该不该出现,由 templet 函数当场决定。用户看到什么,就是什么,没有隐藏、没有冗余、没有侥幸。
fixed 列要设 width,空数据需提前 guard
如果你把操作列设为 fixed: 'right' 却没写 width,表格在 Chrome 下可能错位或滚动条异常。这不是 bug,是 fixed 列必须有明确宽度才能参与布局计算。
另外,后端返回的数据若含空行(如 d === null 或 d.status === undefined),templet 函数里不做防护就会报错中断渲染。务必加一层兜底:
templet: function(d) {
if (!d || typeof d !== 'object') return '<span class="layui-text">数据异常</span>';
// 后续正常判断
if (d.status === 'draft') { ... }
}
最易被忽略的是:状态字段名大小写不一致(比如后端传 status_code,你却写 d.status)、字段嵌套过深(如 d.ext.info.status 却没判 d.ext 是否存在)——这些不会报语法错误,但会让按钮永远不出现,排查起来特别费时间。











