为什么 removeEventListener 不起作用?
why doesn't removeEventListener work?
我不确定这里出了什么问题,但是在 chromium 和 firefox 中进行测试,我发现我在从 javascript.[=13 中的元素中删除 EventListener 时做错了=]
上下文是 canvas 游戏。首先,会显示一个启动画面,您可以在此处单击以开始游戏。单击开始后,我想删除侦听器。
主要关注点是startGame函数中的removeEventListener。它不会引发错误。然后代码执行(我在控制台中看到游戏开始消息,我可以看到 "this" 是 Game 实例)。我完全不明白为什么我每次都继续点击 canvas 运行 startGame。预期的行为是,一旦 EventListener 被移除,单击此处将不会执行任何操作。
求助!
function Game(canvas) {
this.c = canvas;
this.ctx = this.c.getContext("2d");
this.c.width = CANVAS_WIDTH;
this.c.height = CANVAS_HEIGHT;
// Background image
this.bgReady = false;
this.bgImage = new Image();
this.bgImage.onload = function () {
window.g.bgReady = true;
};
this.bgImage.src = MAIN_BACKGROUND;
}
Game.prototype.setSplash = function() {
if (this.bgReady) {
this.ctx.drawImage(window.g.bgImage, 0, 0);
this.ctx.font="48px Helvetica";
this.ctx.textAlign = "center";
this.ctx.fillStyle="rgb(0,0,255)";
this.ctx.fillText("Click To Start",310,240);
document.getElementById("cnvs").addEventListener(
'click',this.startGame.bind(this),true);
} else {
// since setSplash is an early function
// wait a bit for the background image and then try again
setTimeout(this.setSplash.bind(this),100);
console.log("bgImage not ready...");
}
}
Game.prototype.startGame = function() {
console.log("game starting ...");
console.log(this);
// step 1, remove the click listener for this function
// why isn't this working?!
document.getElementById("cnvs").removeEventListener(
'click',this.startGame,true);
}
...
// other stuff ...
function initialize() {
// Get the canvas
var c = document.getElementById("cnvs");
// Create a game object
window.g = new Game(c);
// Set the splash page
g.setSplash();
}
window.onload=initialize;
更多信息:
我也有一个版本,其中非工作删除被写为:
this.c.removeEventListener('click',this.startGame,true);
与上面引用的代码相同的行为。
编辑:回复 mczepiel
的第一个答案
我正在尝试像这样实现你的答案:
Typer.prototype.setSplash = function() {
if (this.bgReady) {
this.ctx.drawImage(window.t.bgImage, 0, 0);
this.ctx.font="48px Helvetica";
this.ctx.textAlign = "center";
this.ctx.fillStyle="rgb(0,0,255)";
this.ctx.fillText("Click To Start",310,240);
var boundFunction = this.startGame.bind(this);
document.getElementById("cnvs").addEventListener(
'click',boundFunction,true,boundFunction);
} else {
// since setSplash is an early function
// wait a bit for the background image and then try again
setTimeout(this.setSplash.bind(this),100);
console.log("bgImage not ready...");
}
}
Typer.prototype.startGame = function(boundFunction) {
console.log("game starting ...");
console.log(this); // strangely, now this is an Object rather
// than Game, it still has the properties of
// Game tho
// step 1, remove the click listener for this function
// still isn't working...
document.getElementById("cnvs").removeEventListener(
'click',boundFunction,true);
}
我想我理解你的建议,但也许不理解。上面的代码仍然没有删除侦听器。任何帮助表示赞赏。
您需要存储对调用 this.startGame.bind(this)
结果的引用,并将相同的值传递给 addEventListener
和 removeEventListener
删除调用期望删除与添加为侦听器的对象完全相同的对象。
可能与 removeEventListener is not working 和其他问题重复,如果您想看到不同版本的同一问题。
编辑未经测试off-the-cuff 建议:
Typer.prototype.setSplash = function() {
if (this.bgReady) {
// draw stuff
var canvasElement = document.getElementById("cnvs");
var dismissSplash = function (evt) {
canvasElement.removeEventListener('click', dismissSplash, true);
this.startGame();
}.bind(this);
canvasElement.addEventListener('click', dismissSplash, true);
} else {
// try to show splash later
}
}
Typer.prototype.startGame = function() {
// start game
}
我不确定这里出了什么问题,但是在 chromium 和 firefox 中进行测试,我发现我在从 javascript.[=13 中的元素中删除 EventListener 时做错了=]
上下文是 canvas 游戏。首先,会显示一个启动画面,您可以在此处单击以开始游戏。单击开始后,我想删除侦听器。
主要关注点是startGame函数中的removeEventListener。它不会引发错误。然后代码执行(我在控制台中看到游戏开始消息,我可以看到 "this" 是 Game 实例)。我完全不明白为什么我每次都继续点击 canvas 运行 startGame。预期的行为是,一旦 EventListener 被移除,单击此处将不会执行任何操作。
求助!
function Game(canvas) {
this.c = canvas;
this.ctx = this.c.getContext("2d");
this.c.width = CANVAS_WIDTH;
this.c.height = CANVAS_HEIGHT;
// Background image
this.bgReady = false;
this.bgImage = new Image();
this.bgImage.onload = function () {
window.g.bgReady = true;
};
this.bgImage.src = MAIN_BACKGROUND;
}
Game.prototype.setSplash = function() {
if (this.bgReady) {
this.ctx.drawImage(window.g.bgImage, 0, 0);
this.ctx.font="48px Helvetica";
this.ctx.textAlign = "center";
this.ctx.fillStyle="rgb(0,0,255)";
this.ctx.fillText("Click To Start",310,240);
document.getElementById("cnvs").addEventListener(
'click',this.startGame.bind(this),true);
} else {
// since setSplash is an early function
// wait a bit for the background image and then try again
setTimeout(this.setSplash.bind(this),100);
console.log("bgImage not ready...");
}
}
Game.prototype.startGame = function() {
console.log("game starting ...");
console.log(this);
// step 1, remove the click listener for this function
// why isn't this working?!
document.getElementById("cnvs").removeEventListener(
'click',this.startGame,true);
}
...
// other stuff ...
function initialize() {
// Get the canvas
var c = document.getElementById("cnvs");
// Create a game object
window.g = new Game(c);
// Set the splash page
g.setSplash();
}
window.onload=initialize;
更多信息:
我也有一个版本,其中非工作删除被写为:
this.c.removeEventListener('click',this.startGame,true);
与上面引用的代码相同的行为。
编辑:回复 mczepiel
的第一个答案我正在尝试像这样实现你的答案:
Typer.prototype.setSplash = function() {
if (this.bgReady) {
this.ctx.drawImage(window.t.bgImage, 0, 0);
this.ctx.font="48px Helvetica";
this.ctx.textAlign = "center";
this.ctx.fillStyle="rgb(0,0,255)";
this.ctx.fillText("Click To Start",310,240);
var boundFunction = this.startGame.bind(this);
document.getElementById("cnvs").addEventListener(
'click',boundFunction,true,boundFunction);
} else {
// since setSplash is an early function
// wait a bit for the background image and then try again
setTimeout(this.setSplash.bind(this),100);
console.log("bgImage not ready...");
}
}
Typer.prototype.startGame = function(boundFunction) {
console.log("game starting ...");
console.log(this); // strangely, now this is an Object rather
// than Game, it still has the properties of
// Game tho
// step 1, remove the click listener for this function
// still isn't working...
document.getElementById("cnvs").removeEventListener(
'click',boundFunction,true);
}
我想我理解你的建议,但也许不理解。上面的代码仍然没有删除侦听器。任何帮助表示赞赏。
您需要存储对调用 this.startGame.bind(this)
结果的引用,并将相同的值传递给 addEventListener
和 removeEventListener
删除调用期望删除与添加为侦听器的对象完全相同的对象。
可能与 removeEventListener is not working 和其他问题重复,如果您想看到不同版本的同一问题。
编辑未经测试off-the-cuff 建议:
Typer.prototype.setSplash = function() {
if (this.bgReady) {
// draw stuff
var canvasElement = document.getElementById("cnvs");
var dismissSplash = function (evt) {
canvasElement.removeEventListener('click', dismissSplash, true);
this.startGame();
}.bind(this);
canvasElement.addEventListener('click', dismissSplash, true);
} else {
// try to show splash later
}
}
Typer.prototype.startGame = function() {
// start game
}