我定义了一个充当堆栈的类,我可以将元素推送到它并撤消/重做这些元素。
export default class Stack {
constructor() {
this.history = [];
this.pointer = -1;
}
push(element) {
this.pointer += 1;
if (this.pointer < this.history.length) { this.history.length = this.pointer; }
this.history.push(element);
}
undo() {
if (this.pointer >= 0) {
// undo element...
this.pointer -= 1;
}
}
redo() {
if (this.pointer < this.history.length - 1) {
this.pointer += 1;
// redo element...
}
}
isEmpty() {
return this.history.length === 0;
}
canUndo() {
return !(this.isEmpty() || this.pointer === -1);
}
canRedo() {
return !(this.isEmpty() || this.pointer === this.history.lenght - 1);
}
...
然后我有另一个对象实例化Stack
对象并显示按钮以使用undo
和redo
方法;但是当我无法执行这些操作时,我需要禁用它们(我在canUndo
中实现了方法canRedo
和Stack
来验证这一点)
我可以在初始化时禁用按钮,但我不知道每次更改堆栈属性时如何调用canUndo
和canRedo
方法,因此我可以禁用/启用他们是恐怖的。对此最好的方法是什么?
注意:按钮是在画布上绘制的,它们不是普通的HTML元素。我正在使用ES6和没有框架。
答案 0 :(得分:0)
似乎你可以在你的堆栈状态中使canUndo
和canRedo
成为一个标志。然后根据stack.canUndo
或stack.canRedo
的状态有条件地将您的按钮渲染为已停用。
constructor() {
this.history = [];
this.pointer = -1;
this.canUndo = false;
this.canRedo = false;
}
只需在canUndo
和canRedo
方法中添加一些逻辑,以便在您从canUndo状态进入cantUndo状态时切换标记。
canUndo() {
const isPossible = !(this.isEmpty() || this.pointer === -1);
this.canUndo = isPossible;
return isPossible;
}
如果你这样做,那么使用堆栈的外部事物只能读取堆栈的属性。
答案 1 :(得分:0)
您可以创建一个侦听器模式:
class Listener {
constructor(){
this.listeners = new Map();
}
on(name, func ){
if(! this.listeners.has(name)){
this.listeners.set(name,[func]);
}else{
this.listeners.get(name).push(func);
}
}
trigger(name,...values){
const l = this.listeners.get(name);
if(!l) return;
l.forEach( func => func(...values) );
}
}
所以可以这样做:
class Stack extends Listener {
constructor(){
super();
}
//in every method that enables the undo state
this.trigger("undo",true);
//in every method that enables the undo state
this.trigger("undo",false);
//in every method that enables the redo state
this.trigger("redo",true);
//in every method that disables the redo state
this.trigger("redo",false);
}
然后,如果你想要动态按钮,例如可以做:
const events = new Stack();
events.on("redo", state => {
const button = document.getElementById("redo");
button.disabled = ! state;
});