Javascript removeEventListener 不起作用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10444077/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Javascript removeEventListener not working
提问by Jinu Joseph Daniel
I have the following code to add eventListener
我有以下代码来添加 eventListener
area.addEventListener('click',function(event) {
app.addSpot(event.clientX,event.clientY);
app.addFlag = 1;
},true);
It is working correctly as expected..Later in another function i tried to remove the event listener using the following code
它按预期正常工作......后来在另一个函数中,我尝试使用以下代码删除事件侦听器
area.removeEventListener('click',function(event) {
app.addSpot(event.clientX,event.clientY);
app.addFlag = 1;
},true);
But the even listener is not removed..Why is it happening?Is there any problem with my removeEventListener()? Note:Here area is something like document.getElementById('myId')
但是偶数监听器没有被删除..为什么会发生?我的removeEventListener()有什么问题吗?注意:这里的区域类似于 document.getElementById('myId')
回答by duri
This is because that two anonymous functions are completely different functions. Your removeEventListener
's argument is not a reference to the function object that was previously attached.
这是因为这两个匿名函数是完全不同的函数。您removeEventListener
的参数不是对先前附加的函数对象的引用。
function foo(event) {
app.addSpot(event.clientX,event.clientY);
app.addFlag = 1;
}
area.addEventListener('click',foo,true);
area.removeEventListener('click',foo,true);
回答by Sirko
You are creating two different functions in both calls. So the second function does not relate in any way to the first one and the engine is able to remove the function. Use a common identifier for the function instead.
您在两次调用中都创建了两个不同的函数。所以第二个函数与第一个函数没有任何关系,引擎可以删除该函数。改用函数的通用标识符。
var handler = function(event) {
app.addSpot(event.clientX,event.clientY);
app.addFlag = 1;
};
area.addEventListener('click', handler,true);
later you can then remove the handler by calling
稍后您可以通过调用删除处理程序
area.removeEventListener('click', handler,true);
回答by Slavik
I find that for the windows object, the last param "true" is required. The remove doesn't work if there is no capture flag.
我发现对于 windows 对象,最后一个参数“true”是必需的。如果没有捕获标志,则删除不起作用。
回答by VectorVortec
If you want to pass local variables to the function called by the event listener, you can define the function inside the function (to get the local variables) and pass the name of the function in the function itself. For example, let's start inside the function that adds the event listener with app as a local variable. You would write a function inside this function such as,
如果要将局部变量传递给事件侦听器调用的函数,可以在函数内部定义函数(获取局部变量)并在函数本身中传递函数名称。例如,让我们从添加事件侦听器的函数内部开始,并将 app 作为局部变量。您将在此函数中编写一个函数,例如,
function yourFunction () {
var app;
function waitListen () {
waitExecute(app, waitListen);
}
area.addEventListener('click', waitListen, true);
}
Then you have what you need to remove it when waitExecute is called.
然后,当调用 waitExecute 时,您需要删除它。
function waitExecute (app, waitListen) {
... // other code
area.removeEventListener('click', waitListen, true);
}
回答by ThiefMaster
To remove it, store the function in a variable or simply use a named function and pass that function to the removeEventListener
call:
要删除它,请将函数存储在变量中,或者简单地使用命名函数并将该函数传递给removeEventListener
调用:
function areaClicked(event) {
app.addSpot(event.clientX, event.clientY);
app.addFlag = 1;
}
area.addEventListener('click', areaClicked, true);
// ...
area.removeEventListener('click', areaClicked, true);
回答by neohope
define your Event Handler first,
首先定义您的事件处理程序,
and then
进而
area.addEventListener('click',handler);
area.removeEventListener('click',handler);
回答by David Edwards
I've encountered a problem with removeEventListener() that needs explaining.
我遇到了需要解释的 removeEventListener() 问题。
I wanted to be able to pass parameters to event listeners, so I wrote a function to generate the event listener, that in turn returns a second function, which calls my intended event listener as a callback.
我希望能够将参数传递给事件侦听器,因此我编写了一个函数来生成事件侦听器,该函数又返回第二个函数,该函数调用我想要的事件侦听器作为回调。
The complete library file is as follows:
完整的库文件如下:
//Event handler constants
function EventHandlerConstants()
{
this.SUCCESS = 0; //Signals success of an event handler function
this.NOTFUNCTION = 1; //actualHandler argument passed to MakeEventHandler() is not a Function object
//End constructor
}
//MakeEventHandler()
//Arguments:
//actualHandler : reference to the actual function to be called as the true event handler
//selfObject : reference to whatever object is intended to be referenced via the "this" keyword within
// the true event handler. Set to NULL if no such object is needed by your true
// event handler specified in the actualHandler argument above.
//args : array containing the arguments to be passed to the true event handler, so that the true
// event handler can be written with named arguments, such as:
// myEventHandler(event, arg1, arg2, ... )
// If your function doesn't need any arguments, pass an empty array, namely [], as the
// value of this argument.
//Usage:
//c = new EventHandlerConstants();
//res = MakeEventHandler(actualHandler, selfObject, args);
//if (res == c.SUCCESS)
// element.addEventListener(eventType, res.actualHandler, true); //or whatever
function MakeEventHandler(actualHandler, selfObject, args)
{
var c = new EventHandlerConstants();
var funcReturn = null; //This will contain a reference to the actual function generated and passed back to
//the caller
var res = {
"status" : c.SUCCESS,
"actualHandler" : null
};
if (IsGenuineObject(actualHandler, Function))
{
res.actualHandler = function(event) {
var trueArgs = [event].concat(args);
actualHandler.apply(selfObject, trueArgs);
};
}
else
{
res.status = c.NOTFUNCTION;
//End if/else
}
//Return our result object with appropriate properties set ...
return(res);
//End function
}
Then I wrote a quick test page to find out if this worked as intended, and allowed me to add AND remove event handlers at will.
然后我写了一个快速测试页面来确定这是否按预期工作,并允许我随意添加和删除事件处理程序。
The HTML test page is as follows:
HTML测试页面如下:
<!DOCTYPE html>
<html>
<head>
<!-- CSS goes here -->
<link rel="stylesheet" type="text/css" href="NewEventTest.css">
<!-- Required JavaScript library files -->
<script language = "JavaScript" src="BasicSupport.js"></script>
<script language = "JavaScript" src="EventHandler6.js"></script>
</head>
<body class="StdC" id="MainApplication">
<button type="button" class="StdC NoSwipe" id="Button1">Try Me Out</button>
<button type="button" class="StdC NoSwipe" id="Button2">Alter The 1st Button</button>
</body>
<script language = "JavaScript" src="NewEventTest.js"></script>
</html>
For completeness, I use the following simple CSS file as well:
为了完整起见,我还使用了以下简单的 CSS 文件:
/* NewEventTest.css */
/* Define standard display settings classes for a range of HTML elements */
.StdC {
color: rgba(255, 255, 255, 1);
background-color: rgba(0, 128, 0, 1);
font-family: "Book Antiqua", "Times New Roman", "Times", serif;
font-size: 100%;
font-weight: normal;
text-align: center;
}
.NoSwipe {
user-select: none; /* Stops text from being selectable! */
}
The test code is as follows:
测试代码如下:
//NewEventTest.js
function GlobalVariables()
{
this.TmpRef1 = null;
this.TmpRef2 = null;
this.TmpRef3 = null;
this.Const1 = null;
this.Handler1 = null;
this.Handler2 = null;
this.Handler3 = null;
this.EventOptions = {"passive" : true, "capture" : true };
//End constructor
}
//Button 1 Initial function
function Button1Initial(event)
{
console.log("Button 1 initial event handler triggered");
//End event handler
}
function Button1Final(event)
{
console.log("Button 1 final event handler triggered");
//End event handler
}
function Button2Handler(event, oldFunc, newFunc)
{
var funcRef = null;
this.removeEventListener("click", oldFunc);
this.addEventListener("click", newFunc, GLOBALS.EventOptions);
//End event handler
}
//Application Setup
GLOBALS = new GlobalVariables();
GLOBALS.Const1 = new EventHandlerConstants();
GLOBALS.TmpRef1 = document.getElementById("Button1");
GLOBALS.TmpRef2 = MakeEventHandler(Button1Initial, null, []);
if (GLOBALS.TmpRef2.status == GLOBALS.Const1.SUCCESS)
{
GLOBALS.Handler1 = GLOBALS.TmpRef2.actualHandler;
GLOBALS.TmpRef1.addEventListener("click", GLOBALS.Handler1, GLOBALS.EventOptions);
//End if
}
GLOBALS.TmpRef1 = MakeEventHandler(Button1Final, null, []);
if (GLOBALS.TmpRef1.status == GLOBALS.Const1.SUCCESS)
{
GLOBALS.Handler3 = GLOBALS.TmpRef1.actualHandler;
//End if
}
GLOBALS.TmpRef1 = document.getElementById("Button2");
GLOBALS.TmpRef2 = document.getElementById("Button1");
GLOBALS.TmpRef3 = Button1Final;
GLOBALS.TmpRef4 = MakeEventHandler(Button2Handler, GLOBALS.TmpRef2, [GLOBALS.Handler1, GLOBALS.Handler3]);
if (GLOBALS.TmpRef4.status == GLOBALS.Const1.SUCCESS)
{
GLOBALS.Handler2 = GLOBALS.TmpRef4.actualHandler;
GLOBALS.TmpRef1.addEventListener("click", GLOBALS.Handler2, GLOBALS.EventOptions);
//End if
}
So, the test to be performed is as follows:
因此,要执行的测试如下:
[1] Attach a click event handler to Button #1;
[1] 将点击事件处理程序附加到按钮 #1;
[2] Test to see if the event handler is invoked when I click on the button;
[2] 测试我点击按钮时是否调用了事件处理程序;
[3] Once that test is passed, click on Button #2, and invoke the event handler attached thereto, which removes the old event handler attached to Button #1, then replaces it with a new event handler.
[3] 一旦该测试通过,单击按钮 #2,并调用附加到其上的事件处理程序,删除附加到按钮 #1 的旧事件处理程序,然后用新的事件处理程序替换它。
Steps [1] and [2] work fine. The event handler is attached, and invoked whenever I click upon the button.
步骤 [1] 和 [2] 工作正常。事件处理程序已附加,并在我单击按钮时调用。
The problem is with Step [3].
问题在于步骤 [3]。
Even though I save a reference to the function generated by MakeEventHandler(), specifically for the purpose of removing that event listener in Step [3], the call to removeEventListener() does NOT remove the event listener. Subsequent clicking on Button #1 fires BOTH event listeners, including the one I supposedly removed!
即使我保存了对由 MakeEventHandler() 生成的函数的引用,特别是为了在步骤 [3] 中删除该事件侦听器,对 removeEventListener() 的调用不会删除事件侦听器。随后单击按钮 #1 会触发两个事件侦听器,包括我应该删除的那个!
Needless to say, this behaviour I find puzzling, despite carefully setting everything up so that the function I specify in the call to removeEventListener() is the self same function I added initially with addEventListener() - according to allthe documentation on the subject I've read (including this thread), passing a reference to the same function for each call shouldwork, but clearly doesn't.
毋庸置疑,尽管仔细设置了所有内容,以便我在调用 removeEventListener() 时指定的函数与我最初使用 addEventListener() 添加的函数相同,但我发现这种行为令人费解 - 根据有关我的主题的所有文档已阅读(包括此线程),为每个调用传递对同一函数的引用应该可以工作,但显然不行。
At Step [1], the test output in the console reads, as expected:
在第 [1] 步,控制台中的测试输出如预期的那样显示:
Button 1 initial event handler triggered
按钮 1 初始事件处理程序被触发
The code is also run, as expected, in Step [2], and a step by step trace of the code reveals that indeed, the code is executed as expected.
代码也按预期在步骤 [2] 中运行,对代码的逐步跟踪显示,代码确实按预期执行。
But in Step [3], whilst the firstclick on Button #1 yields the desired result:
但是在步骤 [3] 中,第一次单击按钮 #1 会产生所需的结果:
Button 1 final event handler triggered
按钮 1 最终事件处理程序被触发
what happens when Button #1 is clicked upon subsequentlyis this:
随后单击按钮 #1 时会发生什么:
Button 1 initial event handler triggered Button 1 final event handler triggered
触发按钮 1 初始事件处理程序 触发按钮 1 最终事件处理程序
Surely, even if the function initially attached to Button #1 still persists in memory, because it was generated within a closure, it should still be detached from the event listener collection for the element? Why is it still connected?
当然,即使最初附加到 Button #1 的函数仍然保留在内存中,因为它是在闭包中生成的,它仍然应该从元素的事件侦听器集合中分离出来吗?为什么它仍然连接?
Or have I encountered some weird bug involving using closures with event listeners, that needs to be reported?
或者我是否遇到过一些奇怪的错误,涉及使用带有事件侦听器的闭包,需要报告?