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
相关产品推荐
相关产品推荐

