ES6从箭头函数(OOP)中删除removeEventListener

3

I have a class like this:

class Hanoi{

   constructor(canvas) {
      //construcor things
   }

   onMouseDown(e) {
      for (var i = 0; i < this.pieces.length; i++) {
         let piece = this.pieces[i];
         if (piece.isClicked(e)) {
            this.isDragging = true;
            this.dragPiece = piece;
            this.bound = evt => this.onMouseMove(evt);
            this.canvas.addEventListener("mousemove", ev => {this.onMouseMove(ev)});
            this.canvas.addEventListener("mouseup", ev =>{this.onMouseUp(ev)});
            this.draw();
         }
      }
   }

   onMouseMove(e) {
      this.dragPiece.x = e.clientX;
      this.dragPiece.y = e.clientY;
      this.draw();
   }

   onMouseUp(e) {
      this.canvas.removeEventListener("mousemove", this.onMouseMove);
      this.canvas.removeEventListener("mouseup", this.onMouseUp);
      this.isDragging = false;
      this.draw();
   }
}

在onMouseDown中添加了两个事件监听器,但由于箭头函数的缘故,在调用onMouseUp时无法删除它们。

如何处理这种情况最好?


有没有不添加事件处理程序的原因,例如 this.canvas.addEventListener("mouseup", this.onMouseUp);?你基本上是使用一个已经有引用的普通函数,那么为什么要在其中插入箭头函数呢? - arbuthnott
因为此处的 "this." 将引用 canvas 而不是该类。 - Rodrigo Vázquez
为什么要在循环中将多个相同的处理程序绑定到同一个元素上?如果您使用下面的解决方案,addEventListener 将防止重复绑定,因为它们是相同的函数对象。 - spanky
2个回答

6

请尝试以下方法:

...

constructor(canvas) {
  this.onMouseMove = this.onMouseMove.bind(this);
  this.onMouseUp = this.onMouseUp.bind(this);
}

onMouseDown(e) {
  ...
  this.canvas.addEventListener("mousemove", this.onMouseMove);
  this.canvas.addEventListener("mouseup", this.onMouseUp});
  ...
}

onMouseUp(e) {
  this.canvas.removeEventListener("mousemove", this.onMouseMove);
  this.canvas.removeEventListener("mouseup", this.onMouseUp);
  ...
}


先生,非常感谢您!你太棒了! - Rodrigo Vázquez
1
请解释问题的原因,以帮助初学者理解他们的错误。由于我的代码没有解释,请先不要点赞。 - try-catch-finally
就我所知,在构造函数中,您将“this”绑定为这些方法的类,因此您的范围将如您所愿,但是这样您将侦听器分配给方法this.onMouseMove而不是匿名函数,因此您可以稍后删除侦听器。或者,如下所建议的那样,您可以定义一个变量来使用箭头函数,然后稍后使用该变量。 - jacob.mccrumb

0

如果您想稍后引用该函数(例如删除),最好使用命名的普通函数定义。但是,如果您坚持使用箭头函数,则仍然可以按如下方式操作:

您可以将箭头函数表达式分配给一个变量,同时将其作为回调传递。然后通过该名称进行删除。因此,如果您不想在全局命名空间中乱七八糟地放置函数,您始终可以使用周围的函数对象来存储箭头函数。在这种特殊情况下,我将“click”事件侦听器的回调命名为“X”,并将“mouseup”箭头函数存储在该函数对象的“muel”属性下,当触发时自行删除。

像这样;

btt.addEventListener("click", function X(e){
  e.target.textContent === "Add Listener" ? (e.target.addEventListener("mouseup", X.muel = e => {
                                                                          e.target.removeEventListener("mouseup", X.muel);
                                                                          console.log("mouse up fired and event listener removed");
                                                                        }),
                                             e.target.textContent = "Remove Listener")
                                          : e.target.textContent = "Add Listener";
                              });
<button id="btt">Add Listener</button>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接