table.on("edit") 是捕获编辑完成的唯一入口,需用 lay-filter 精确匹配,在失焦时触发(回车不触发),获取 obj.field、obj.value 和整行原始数据 obj.data;提交前须手动构造变更集、显式设置 contentType 为 application/json 并 JSON.stringify,避免全量提交或缓存不同步。
table.on("edit") 是唯一能捕获编辑完成的入口
layui 表格不会自动保存任何修改,table.on("edit") 是你必须绑定的事件——它在用户失焦或点击其他单元格时触发,但**回车键默认不触发**。如果你没监听这个事件,编辑完的数据就只存在 dom 里,刷新页面即丢失。
常见错误现象:点了编辑、输完内容、直接点保存按钮,结果后端收不到变化;或者点了编辑又快速点别的地方,obj.value 是空或旧值。
- 必须用
lay-filter值(如"user-table")精确匹配事件,写错一个字符就监听不到 -
obj.data是整行原始数据,含所有字段;obj.field是当前被编辑列的field名;obj.value是输入框最终字符串值(注意:checkbox 编辑返回"true"/"false"字符串,不是布尔值) - 别在回调里直接改
obj.data[field] = value——这改的是副本,不影响table.cache或后续table.getData()
提交前必须手动处理 data 和 contentType
直接把 table.getData() 塞进 $.ajax({ data: ... }) 会导致后端收到 application/x-www-form-urlencoded 格式,JSON 字段被当作文本解析,大概率 400 错误或字段为空。
正确做法是显式声明 JSON 类型并序列化:
$.ajax({
url: "/api/save-users",
method: "POST",
contentType: "application/json",
data: JSON.stringify({ rows: table.getData() })
});
- 漏掉
contentType: "application/json",Express/Koa/Spring Boot 默认按表单解析,@RequestBody拿不到数据 -
table.getData()默认只返回当前页数据;如果启用了分页且要全量保存,得手动拼接各页缓存,或改用单页模式 - 后端接收字段名(如这里的
rows)必须和接口文档一致,Layui 不做 key 映射
只提交变更行,别一股脑发全量
用户只改了一格,后端却收到几百行数据——这不是健壮性,是浪费带宽、增加 SQL 压力、掩盖真实业务意图。
更合理的做法是在 table.on("edit") 里记录最小变更集:
- 用
e.tr.data("index")拿到当前行在table.cache中的索引 - 查
table.cache["user-table"][index]得到原始行对象,对比e.value判断是否真有变更 - 构造轻量更新对象,例如
{ id: 123, email: "new@x.com" },避免传整行 - 如果表格有主键字段(如
id),后端可用UPDATE ... WHERE id = ?精准更新,不用全量比对
新增行后,table.cache 不会自动同步
调用 table.reload({ data: newData }) 后,新行确实显示了,但 table.cache["user-table"] 仍是旧数组——因为 reload 会重建缓存,但你传入的 data 若没包含原始 lay-id 或结构不一致,缓存可能缺失关键元信息。
实操建议:
- 新增行时,手动给对象加唯一
lay-id(如Date.now()),否则table.cache无法定位该行 - 新增后立即调用
table.cache["user-table"].push(newRow),再table.reload(),确保缓存与视图一致 - 若用
table.addRow()(Layui 2.8+),它内部会维护缓存,但老版本仍需手动补位 - 移动端或 Safari 下,动态插入行后可能渲染延迟,加
setTimeout(() => table.resize(), 10)防止列宽错乱影响编辑焦点
最易被忽略的一点:table.cache 是引用类型,但 layui 内部做了深拷贝,直接改 table.cache["x"][i].email = "a@b" 无效;必须用 table.cache["x"][i] = { ...old, email: "a@b" } 替换整项。


















