Vanilla JS:如何从另一个对象跟踪对象的属性?

时间:2017-09-13 14:29:18

标签: javascript

我定义了一个充当堆栈的类,我可以将元素推送到它并撤消/重做这些元素。

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对象并显示按钮以使用undoredo方法;但是当我无法执行这些操作时,我需要禁用它们(我在canUndo中实现了方法canRedoStack来验证这一点)

我可以在初始化时禁用按钮,但我不知道每次更改堆栈属性时如何调用canUndocanRedo方法,因此我可以禁用/启用他们是恐怖的。对此最好的方法是什么?

注意:按钮是在画布上绘制的,它们不是普通的HTML元素。我正在使用ES6和没有框架

2 个答案:

答案 0 :(得分:0)

似乎你可以在你的堆栈状态中使canUndocanRedo成为一个标志。然后根据stack.canUndostack.canRedo的状态有条件地将您的按钮渲染为已停用。

  constructor() {
    this.history = [];
    this.pointer = -1;
    this.canUndo = false;
    this.canRedo = false;
  }

只需在canUndocanRedo方法中添加一些逻辑,以便在您从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;
});