拖动排序后点撤销,一次退回两步,再点一次直接回到初始顺序。历史栈长度显示 2,实际记录了 3 次操作。第一次遇到会往复杂处想,其实漏掉的多是个小前提。
setHistory(h => [...h, structuredClone(rows)]); // 或使用 immer 生成的不可变快照
每次入栈存的是同一个数组引用,浅拷贝只复制了外层,后续修改把历史里的内容一起改了。比较时又用引用判断是否重复。这一点先确认清楚,后面就不用反复试。
碰到「撤销重做历史栈」这类问题,我习惯先把当前配置原样备份一份,改坏了立刻换回来,不用现场推。新版本先放一台机器上跑一天再全量,问题一般在这段时间暴露。
备份不是备了就行,恢复一次才算数,很多备份文件打开才发现是空的。
具体做法是,入栈时做深拷贝或存不可变快照;用结构共享减少内存占用;记录操作前后的差异而不是整份数据;连续做三次操作再逐步撤销 核对每一步。
改完照着核一遍,三次操作后连续撤销三次,每次只回退一步,最终回到初始顺序。
