必须自行维护变更状态,不能依赖table.on('edit')事件获取所有修改:初始化时为每行挂__changed对象,edit触发时记录字段与新值,提交前通过__changed提取真实变更项。

监听 edit 事件只能捕获单次修改,不是“所有”
layui 的 table.on('edit(...)') 每次只触发一次,对应一个单元格失焦,它不记录历史、不聚合变更、也不提供“哪些字段被改过”的快照。想拿到「所有被修改过的单元格」,必须自己维护状态,不能依赖事件回调本身。
用 data-index + field 构建变更标记表
最轻量且稳定的做法:在表格初始化后,为每一行数据挂载一个变更记录对象(比如 __changed),每次 edit 触发时往里写入字段名和新值。注意别直接改原始数据对象的 key(可能影响渲染或校验逻辑)。
- 初始化时遍历
table.cache['yourFilter'],给每行加__changed: {} - 在
edit回调里:obj.data.__changed[obj.field] = obj.value - 提交前用
Object.keys(row.__changed).length > 0判断是否改动,再用Object.entries(row.__changed)提取所有「字段→新值」对 - 避免用
JSON.stringify对比前后快照——性能差,且无法区分空字符串、null、undefined等语义差异
table.getData() 返回的是当前页数据,不是变更集
table.getData() 拿到的是当前页渲染后的全部行数据(含未改项),它不标记哪些字段被动过。如果你只想要真正改过的单元格,必须结合前面的 __changed 标记,而不是对整页数据做全量 diff。
- 分页场景下,
table.getData()默认只返回当前页;若要跨页收集变更,得遍历table.cache['yourFilter']全量缓存 - 不要在
edit回调里直接调用table.getData()并逐行深比较——既慢又不可靠,尤其当字段含日期、浮点数或嵌套对象时 - 如果用了
parseData处理后端响应,确保你挂载的__changed不被覆盖(它在 cache 里,不在原始res.data中)
注意 obj.tr 和 obj.data 的生命周期差异
obj.tr 是 DOM 引用,obj.data 是缓存数据引用,二者在表格重载(reload)后都会失效。你存的 __changed 如果只挂在 obj.data 上,表格翻页或刷新后就丢了——除非你把它同步写回 table.cache 对应索引位置。
- 安全写法:
const cache = table.cache['yourFilter']; const idx = obj.tr.dataset.index; if (cache[idx]) cache[idx].__changed = cache[idx].__changed || {}; cache[idx].__changed[obj.field] = obj.value; - 别依赖
obj.row(旧版兼容字段),它不一定等于obj.data,尤其在使用initSort或自定义done时 - 如果表格支持新增行(
addRow),新增行的data可能没有id,但__changed仍可照常记录——只是提交时需单独走新增逻辑
真正难的不是“怎么取”,而是“什么时候清”。用户改完又改回去、跨页操作、重载表格却不重置标记……这些边界情况比获取逻辑本身更消耗调试时间。











