Как сделать функцию отмены / повтора - PullRequest
0 голосов
/ 29 января 2019

Я хочу добавить функцию undo/redo в мой скрипт.Я осмотрелся и увидел некоторые предложения, большинство из которых рекомендовали использовать command pattern.

Я искал примеры, учебные пособия или что-то еще, которые объясняют, как это работает, но я ничего не смог найти.

Функция должна работать над одной страницей, я имею в виду, что после перезагрузки страницы она должна redo/undo думать в последний раз.

Ну, я не знаю, как работает шаблон командыЯ думаю о создании объекта, сохранении имени функции, старого и нового значения - но я не уверен, что это эффективный способ сделать это или нет.

Может бытькто-нибудь может привести небольшой пример того, как должен искать код для функции undo/redo.

1 Ответ

0 голосов
/ 29 января 2019

Обычно у вас есть 2 варианта:

Шаблон Memento

  • Легко реализовать, во многих случаях он неэффективен.

Додействие применяется, вы делаете снимок текущего состояния и сохраняете его в массив.Этот снимок - Памятка .

Если пользователь хочет отменить, вы просто pop последний памятку и примените его.Программа возвращается в состояние, в котором она находилась до применения последнего действия.

Этот шаблон ограничен с точки зрения эффективности.Каждый сувенир является относительно большим, поскольку он отражает все текущее состояние.

Но это также проще всего реализовать, поскольку вам не нужно явно кодировать все случаи и их обратные действия, которые вам нужны в шаблоне команд (см. Ниже).

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>

Шаблон команды

  • Сложнее в реализации, но эффективно использует память.

Каждое действиеимеет соответствующее обратное действие (команду).Например, каждый раз, когда вы добавляете символ в текстовое поле, вы сохраняете обратную функцию;который должен удалить символ в этой позиции.

Если пользователь хочет отменить, вы применяете обратное действие.

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 Я использую UndoManager в своих проектах в качестве стека для моих команд,

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...