table.on('edit') 是唯一可靠入口,它只在回车、点击其他单元格或空白处后触发,自带 obj.field、obj.value 等参数;需确保 lay-filter 一致,防抖、比对、类型清理缺一不可,成功后用 updatecell 或手动同步 dom,并用 settimeout(0) 更新合计行。

table.on('edit') 是唯一可靠入口,别绑原生 blur
直接给 .layui-table-edit 绑 blur 事件会误触发——点排序、切分页、弹 layer 都会让输入框失焦,但用户根本没想保存。Layui 封装的 table.on('edit(filterName)') 才是正解:它只在真正完成一次编辑(回车、点击其他单元格、点击空白处)后触发,并自带 obj.field、obj.value、obj.oldValue 和 obj.data。
常见错误是监听了 edit 却没传对 filter 名,比如渲染时写 lay-filter="userTable",监听却写成 table.on('edit(user-list)'),结果事件压根不触发。
- 确保表格初始化时设置了
lay-filter="xxx",且监听时完全一致 - 回调里别直接用
$(this).val()——this是td,不是input;要用$(obj.elem).find('input').val()或直接信obj.value - 如果列用了
templet,obj.value通常是空字符串,必须手动从模板里取值
保存前必须做三件事:防抖、比对、类型清理
用户连打几个字就发七八次请求?那是没加防抖。后端返回成功但界面上还是旧值?大概率没比对原始值就盲目提交。保存逻辑不能只写 $.ajax,得先兜住这三步:
- 用
clearTimeout+setTimeout(..., 300)防抖,避免高频触发 - 从
table.cache['xxx'][index]拿原始行,对比obj.value是否真有变化(注意字符串"12"和数字12不等) - 对数字字段用
parseFloat(obj.value),文本字段用$.trim(obj.value),空值统一转''或0,别把带空格的字符串直接交出去
漏掉任何一项,都可能引发重复提交、400 错误或界面与缓存错位。
保存成功后别 reload 整表,用 updateCell 或手动同步 DOM
table.reload() 会丢页码、清排序、重置勾选状态,纯属杀鸡用牛刀。正确做法是精准更新当前行:
- Layui ≥2.8:调用
layui.table.updateCell({ id: 'xxx', field: obj.field, value: newValue, index: obj.data.LAY_TABLE_INDEX }),它自动同步缓存和 DOM - 老版本:手动改
table.cache['xxx'][index][obj.field] = newValue,再用$(obj.tr).find('td[data-field="' + obj.field + '"]')找到单元格,.text(newValue)更新显示 - 如果该列参与合计计算(比如金额列),还得立刻重算总和并填进
.layui-table-total td[data-field="amount"],否则翻页回来就露馅
合计行更新必须加 setTimeout(0),否则 DOM 写不进去
在 table.on('edit') 回调里直接操作 .layui-table-total td 经常失败——因为 Layui 内部是异步更新 DOM 的,此时合计行可能还没渲染完,或者正在重绘。最稳的解法是延迟一帧:
setTimeout(function() {
var total = 0;
layui.table.cache['xxx'].forEach(function(row) {
total += parseFloat(row.amount) || 0;
});
$('.layui-table-total td[data-field="amount"]').text(total.toFixed(2));
}, 0);
这个 setTimeout(0) 不是可有可无的“保险”,而是强制把 DOM 写入放到下一个事件循环,确保目标元素已就绪。fixed 列下还要额外更新 .layui-table-fixed-r .layui-table-total td,不然右侧合计会被遮住。











