可视化编辑器撤销重做怎么实现才不会乱?

Good“培乐 阅读 5

我在做一个拖拽组件的可视化编辑器,现在想加撤销重做功能,但每次操作后状态同步老出问题。比如拖动一个元素后撤销,位置没变回来,或者重做时报错。

我试过用一个数组存历史快照,每次操作就 push 一个新状态,但数据量大了特别卡。也看过别人用命令模式,但不太会写。有没有轻量又稳定的方案?

目前状态是这样存的:history.push(JSON.parse(JSON.stringify(currentState))),但感觉这不是长久之计……

我来解答 赞 5 收藏
二维码
手机扫码查看
1 条解答
夏侯香利
别存全量快照了,用命令模式只记录增量变化。

// 每个操作就是一个命令对象
const commands = {
move: (id, oldPos, newPos) => ({
execute: () => updatePos(id, newPos),
undo: () => updatePos(id, oldPos)
}),
resize: (id, oldSize, newSize) => ({
execute: () => updateSize(id, newSize),
undo: () => updateSize(id, oldSize)
})
};

// 撤销重做栈
let history = [];
let pointer = -1;

function doCommand(cmd) {
cmd.execute();
history = history.slice(0, pointer + 1); // 干掉后面的
history.push(cmd);
pointer++;
}

function undo() {
if (pointer >= 0) history[pointer--].undo();
}

function redo() {
if (pointer < history.length - 1) history[++pointer].execute();
}


拖动时只存 { id, oldPos, newPos } 这点数据,撤销时反向操作,搞定。
点赞 3
2026-03-01 12:07