我正在考虑在角度应用程序中实现撤消,重做功能的方法。
第一个也是最基本的想法是使用一个完全描述app内部的模型,让我们称之为type DataIn struct {
Code int `json:"code"`
ID string `json:"id"`
Data interface{} `json:"data"`
}
func (s DataIn) toInt() int {
switch t := s.Data.(type)
case int:
i, _ := strings.Atoi(fmt.Sprintf("%v",s.Data))
return i
}
// using it
sampleData := someStruct{
Number1: datain.toInt(),
}
。在每个值得记录的更改中,您只需创建一个AppModel
的新对象,然后将其推送到堆栈并更新currentIndex。
在绝对最坏的情况下,AppModel的对象必须填写500个文本字段,平均长度为20个字符。每次更新都有10000个字符或10kB。
这个号码有多糟糕?我不认为是否会导致内存问题,但是每次推送到堆栈时它是否会使应用程序冻结?这是一个基本的实现:
AppModel
我能想到的另一个选择是存储执行 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--];
}
和redo
操作的函数调用。这种方法需要我也存储需要调用函数的对象。这些对象可能会被用户删除,因此还必须有一种方法来重新创建对象。当我输入时,这会变得很痛苦:)
您推荐什么方式?
答案 0 :(得分:1)
这就是为什么建议不要将状态置于单个对象中,而是与每个模块具有适当数量的属性的(业务)模块一起使用的原因。
我建议使用Redux框架(如NGRX或NGXS)进行状态管理。对于NGRX,有一个meta-reducer-library https://www.npmjs.com/package/ngrx-wieder,可以像这样包装您的NGRX reducer:
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