You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript中removeEventListener移除点击事件监听不生效问题求解

问题根源

Function.prototype.bind()每执行一次都会生成一个全新的函数实例,你在添加事件监听时临时执行this.ticTacToeControl.bind(this)生成的函数引用,和移除监听时传入的原始this.ticTacToeControl引用完全不一致,浏览器无法匹配到要移除的监听函数,因此移除操作失效。

解决方案

方案1:提前绑定一次,存为实例唯一引用

在Controller构造阶段就将绑定好this的方法存为实例属性,添加、移除监听都复用这个唯一引用即可:

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

class Controller {
      constructor() {
        // 仅绑定一次,存储为实例属性,全局唯一引用
        this.boundTicTacToeControl = this.ticTacToeControl.bind(this);
        navigationView.addHoverEventHandlers(navigationView.hoverFunction);
        navigationView.addClickHandler(this.showContent.bind(this));
      }
    
      showContent() {
        // 多次触发showContent时先移除旧监听,避免重复绑定
        ticTacToeView.removeClickEventHandler(this.boundTicTacToeControl);
        ticTacToeView.renderContent(navigationView.clickedContent);
        // 复用提前绑定好的实例属性
        ticTacToeView.addClickEventHandler(this.boundTicTacToeControl);
        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.boundTicTacToeControl);
          }
        }
      }
    }

方案2:用类箭头函数自动绑定this

也可以直接将回调方法定义为类实例的箭头函数,自动绑定this到实例,不需要手动执行bind,天然是唯一引用:

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.removeClickEventHandler(this.ticTacToeControl);
        ticTacToeView.renderContent(navigationView.clickedContent);
        ticTacToeView.addClickEventHandler(this.ticTacToeControl);
        ticTacToeView.addHoverHandler(ticTacToeView.hoverFunction);
      }
    
      // 箭头函数自动绑定this到当前实例,引用唯一不需要额外bind
      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);
          }
        }
      }
    }

内容的提问来源于stack exchange,提问作者Aljaz Gracner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 17:54:03