我想添加一个undo/redo
我的脚本中的函数。我环顾四周,看到了一些建议,其中大多数建议使用command pattern
.
该函数必须在一页上运行 - 重新加载页面后,该函数必须能够redo/undo
最后的事情。
我不知道命令模式是如何工作的,我想创建一个对象,来存储函数的名称、旧值和新值 - 但我不确定这是否是执行此操作的有效方法或不是。
也许有人可以给我一个小例子,如何编写undo/redo
函数应该看起来。
有两种常见的实现撤消/重做的方法:
- The 纪念品图案 https://en.wikipedia.org/wiki/Memento_pattern,您可以在其中捕获整体current state https://en.wikipedia.org/wiki/State_(computer_science).
它很容易实现,但内存效率低下,因为您需要存储整个状态的类似副本。
- The 命令模式 https://en.wikipedia.org/wiki/Command_pattern,你捕获的地方命令/动作影响国家的;这当前行动这是逆动作.
这更难实现,因为对于应用程序中的每个可撤消操作,您必须显式编码其相反操作,但它的内存效率要高得多,因为您只存储影响状态的操作。
现在让我们详细说明这两种模式:
纪念品模式
在应用操作之前,您可以拍摄当前状态的快照并将其保存到数组中。那个快照是Memento.
如果用户想要撤消,您只需pop
最后的纪念品并应用它。程序返回到应用最后一个操作之前的状态。
这种模式需要大量内存;每个纪念品都相对较大,因为它捕获了whole当前状态。
但这也是最容易实现的,因为您不需要在命令模式中显式编码所有情况及其相反的操作(见下文)。
const mementos = []
const input = document.querySelector('input')
function saveMemento() {
mementos.push(input.value)
}
function undo() {
const lastMemento = mementos.pop()
input.value = lastMemento ? lastMemento : input.value
}
<h4> Type some characters and hit Undo </h4>
<input onkeydown="saveMemento()" value="Hello World"/>
<button onclick="undo()">Undo</button>
命令模式
对于用户执行的每个操作,您还保存相应的inverse动作/命令。例如,每次在文本框中添加字符时,都会保存反函数;也就是删除该位置的字符。
如果用户想要撤消,您可以弹出最后一个相反的操作/命令并应用它。
const commands = []
const input = document.querySelector('input')
function saveCommand(e) {
commands.push({
// the action is also saved for implementing redo, which
// is not implemented in this example.
action: { type: 'add', key: e.key, index: input.selectionStart },
inverse: { type: 'remove', index: input.selectionStart }
})
}
function undo() {
let value = input.value.split('')
const lastCommand = commands.pop()
if (!lastCommand) return
switch (lastCommand.inverse.type) {
case 'remove':
value.splice(lastCommand.inverse.index, 1)
break;
}
input.value = value.join('')
}
<h4> Type some characters and hit Undo </h4>
<input onkeydown="saveCommand(event)" value="Hello World"/>
<button onclick="undo()">Undo</button>
我编写的代码片段仅在添加字符时起作用,然后单击撤消以返回到添加字符之前的状态,因此它们对您应该如何实现这一点过于简单化。
尽管如此,我认为它们展示了两种模式的核心概念。
FWIW我正在使用撤消管理器 https://github.com/ArthurClemens/Javascript-Undo-Manager在我的项目中作为我的命令的堆栈。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)