【问题标题】:Javascript's removeEventListener not workingJavascript removeEventListener 不起作用
【发布时间】:2021-11-10 22:30:16
【问题描述】:

我已经尝试了一些解决方案,例如回调函数都是相同的。我仍然无法让它工作。

视图模块内的 removeClickEventHandler 函数不起作用。事件侦听器从控制器应用。我从视图模块中提取了一些代码,但控制器模块保持原样。

控制器代码:

import navigationView from "./view/navView.js";
import ticTacToeView from "./view/ticTacToeView.js";
import ticTacModule from "./modules/ticTacModule.js";

class Controller {
      constructor() {
        navigationView.addHoverEventHandlers(navigationView.hoverFunction);
        navigationView.addClickHandler(this.showContent.bind(this));
      }
    
      showContent() {
        ticTacToeView.renderContent(navigationView.clickedContent);
        ticTacToeView.addClickEventHandler(this.ticTacToeControl.bind(this));
        ticTacToeView.addHoverHandler(ticTacToeView.hoverFunction);
      }
    
      ticTacToeControl(clickedBox) {
        if (ticTacToeView.checkIfBoxEmpty(clickedBox)) {
          ticTacToeView.createMark(clickedBox, ticTacModule.activePlayer);
          ticTacModule.updateBoardState(clickedBox);
          ticTacModule.changeActivePlayer();
          ticTacToeView.highlightActivePlayer(ticTacModule.activePlayer);
          ticTacModule.checkForWinner();
          if (ticTacModule.winner) {
            ticTacToeView.renderWinner(ticTacModule.winner);
            ticTacToeView.removeClickEventHandler(this.ticTacToeControl);
          }
        }
      }
    }

这是视图模块代码:

import View from "./View.js";

class TicTacToeView extends View {

  addClickEventHandler(fn) {
    const ticTacContainer = document.querySelector(".tic-tac-toe");
    ticTacContainer.addEventListener("click", fn, true);
  }

  removeClickEventHandler(fn) {
    const ticTacContainer = document.querySelector(".tic-tac-toe");
    ticTacContainer.removeEventListener("click", fn, true);
  }
}
export default new TicTacToeView();

【问题讨论】:

  • 很可能您的函数引用正在改变(您确定this.ticTacToeControl 是同一个引用吗?)或者使用querySelector 选择的元素不同(在页?)。
  • 似乎元素引用或函数引用在调用之间发生了变化。一个简单的解决方法是从 addListener 函数返回一个 removeListener 函数,以确保(通过闭包)相同的函数和元素被 bieng 访问。
  • 这两个函数都对我有用:jsfiddle.net/dqfw4hcm/1 请提供minimal reproducible example
  • @pilchard 有必要吗?它会改变什么吗?我的示例显示提供的代码有效并且函数引用发生了变化。如果没有更多信息,我们将无能为力。

标签: javascript model-view-controller publish-subscribe


【解决方案1】:

bind 使用新引用创建一个新函数。 this.ticTacToeControlthis.ticTacToeControl.bind(this) 是两个不同的函数,有两个不同的引用。将函数引用存储在一个变量中,并使用它来删除事件侦听器。

class Controller {
  constructor() {
    navigationView.addHoverEventHandlers(navigationView.hoverFunction);
    navigationView.addClickHandler(this.showContent.bind(this));
  }

  showContent() {
    ticTacToeView.renderContent(navigationView.clickedContent);
    this.handler = this.ticTacToeControl.bind(this);
    ticTacToeView.addClickEventHandler(this.handler);
    ticTacToeView.addHoverHandler(ticTacToeView.hoverFunction);
  }

  ticTacToeControl(clickedBox) {
    if (ticTacToeView.checkIfBoxEmpty(clickedBox)) {
      ticTacToeView.createMark(clickedBox, ticTacModule.activePlayer);
      ticTacModule.updateBoardState(clickedBox);
      ticTacModule.changeActivePlayer();
      ticTacToeView.highlightActivePlayer(ticTacModule.activePlayer);
      ticTacModule.checkForWinner();
      if (ticTacModule.winner) {
        ticTacToeView.renderWinner(ticTacModule.winner);
        ticTacToeView.removeClickEventHandler(this.handler);
      }
    }
  }
}

【讨论】:

  • 谢谢!现在可以了。我没有意识到 bind 创建了一个新功能。对代码非常陌生,经过几个小时的挫折后,我什至懒得做一个抽象的例子。不过,再次感谢您找到解决方案。
猜你喜欢
  • 2018-03-24
  • 1970-01-01
  • 2022-12-31
  • 2017-09-23
  • 2013-05-15
  • 2014-09-02
相关资源
最近更新 更多