【问题标题】:undo redo functionality in Angular app撤消 Angular 应用程序中的重做功能
【发布时间】:2018-09-09 06:48:58
【问题描述】:

我正在考虑在 Angular 应用中实现撤消、重做功能的方法。

第一个也是最基本的想法是使用一个完全描述应用程序内部的模型,我们称之为AppModel。在每个值得记录的更改中,您只需创建一个 AppModel 的新对象并将其推送到堆栈并更新 currentIndex。

在绝对最坏的情况下,AppModel 的对象必须填写 500 个文本字段,平均长度为 20 个字符。每次更新 10000 个字符或 10kB。

这个数字有多糟糕?我不认为这会导致内存问题,但是每次推送到堆栈时都会使应用程序冻结吗?这是一个基本的实现:

  historyStack: AppModel[];
  currentIndex:number = -1;

  push(newAppModel:AppModel){
    //delete all after current index
    this.historyStack.splice(++this.currentIndex, 0, newAppModel);
  }

  forward(){
    if(this.currentIndex < this.historyStack.length-1){
      this.currentIndex++;
      return this.historyStack[this.currentIndex];
    }
    return this.historyStack[this.currentIndex];
  }
  back(){
    return this.historyStack[this.currentIndex--];
  }

我能想到的另一个选项是存储执行redoreverse 操作的函数调用。这种方法还需要我存储需要调用函数的对象。这些对象可能会被用户删除,因此还必须有一种方法来重新创建这些对象。当我打字时,这变得越来越痛苦:)

你推荐什么方式?

【问题讨论】:

标签: angular undo-redo


【解决方案1】:

这就是为什么建议不要将状态放在单个对象中,而是与(业务)模块一起使用,其中每个模块都有合理数量的属性。

我建议使用像 NGRX 或 NGXS 这样的 Redux 框架来进行状态管理。对于 NGRX,有一个元减速器库 https://www.npmjs.com/package/ngrx-wieder 可以像这样包装您的 NGRX 减速器:

const reducer = (state, action: Actions, listener?: PatchListener) =>
  produce(state, next => {
    switch (action.type) {
      case addTodo.type:
        next.todos.push({id: id(), text: action.text, checked: false})
        return
      case toggleTodo.type:
        const todo = next.todos.find(t => t.id === action.id)
        todo.checked = !todo.checked
        return
      case removeTodo.type:
        next.todos.splice(next.todos.findIndex(t => t.id === action.id), 1)
        return
      case changeMood.type:
        next.mood = action.mood
        return
      default:
        return
    }
}, listener)

const undoableReducer = undoRedo({
  track: true,
  mergeActionTypes: [
    changeMood.type
  ]
})(reducer)

export function appReducer(state = App.initial, action: Actions) {
  return undoableReducer(state, action)
}

这样您就不必一遍又一遍地为每个模块的 reducer 编写撤消/重做逻辑,只需将其包装在 meta reducer 中即可。并且您可以排除不需要撤消的状态的重要部分。您可以在此处找到完整的 Stackblitz 示例,以及实现代码的基本部分(使用 ImmerJS 进行修补):https://nils-mehlhorn.de/posts/angular-undo-redo-ngrx-redux

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-27
    • 2013-10-03
    • 1970-01-01
    • 2014-05-26
    • 1970-01-01
    • 1970-01-01
    • 2011-01-26
    相关资源
    最近更新 更多