Javascript removeEventListener不工作

Javascript removeEventListener不工作,javascript,events,addeventlistener,Javascript,Events,Addeventlistener,我有以下代码来添加eventListener area.addEventListener('click',function(event) { app.addSpot(event.clientX,event.clientY); app.addFlag = 1; },true); 正如预期的那样,它工作正常。稍后在另一个函数中,我尝试使用以下代码删除事件侦听器 area.removeEventListener('cli

我有以下代码来添加eventListener

 area.addEventListener('click',function(event) {
              app.addSpot(event.clientX,event.clientY);
              app.addFlag = 1;
          },true);
正如预期的那样,它工作正常。稍后在另一个函数中,我尝试使用以下代码删除事件侦听器

 area.removeEventListener('click',function(event) {
              app.addSpot(event.clientX,event.clientY);
              app.addFlag = 1;
          },true);
但是偶数侦听器没有被删除..为什么会发生这种情况?我的removeEventListener()有问题吗?
注意:此处区域类似于document.getElementById('myId')

要删除它,请将函数存储在变量中,或者只需使用命名函数并将该函数传递给
removeEventListener调用:

function areaClicked(event) {
    app.addSpot(event.clientX, event.clientY);
    app.addFlag = 1;
}

area.addEventListener('click', areaClicked, true);
// ...
area.removeEventListener('click', areaClicked, true);

这是因为两个匿名函数是完全不同的函数。
removeEventListener
的参数不是对先前附加的函数对象的引用

function foo(event) {
              app.addSpot(event.clientX,event.clientY);
              app.addFlag = 1;
          }
 area.addEventListener('click',foo,true);
 area.removeEventListener('click',foo,true);

首先定义事件处理程序

然后

area.addEventListener('click',handler);
area.removeEventListener('click',handler);

您正在两个调用中创建两个不同的函数。因此,第二个功能与第一个功能没有任何关系,发动机能够删除该功能。改为使用函数的公共标识符

var handler = function(event) {
              app.addSpot(event.clientX,event.clientY);
              app.addFlag = 1;
          };
area.addEventListener('click', handler,true);
稍后,您可以通过调用

area.removeEventListener('click', handler,true);

如果要将局部变量传递给事件侦听器调用的函数,可以在函数内部定义函数(以获取局部变量),并在函数本身中传递函数的名称。例如,让我们从函数内部开始,该函数使用app作为局部变量添加事件侦听器。你可以在这个函数里面写一个函数,比如

function yourFunction () {
    var app;

    function waitListen () {
        waitExecute(app, waitListen);
    }

    area.addEventListener('click', waitListen, true);
}
然后,在调用waitExecute时,您就有了删除它所需的内容

function waitExecute (app, waitListen) {
    ... // other code
    area.removeEventListener('click', waitListen, true);
}

我遇到了removeEventListener()的问题,需要解释

我希望能够将参数传递给事件监听器,因此我编写了一个函数来生成事件监听器,该函数反过来返回第二个函数,该函数作为回调调用预期的事件监听器

完整的库文件如下所示:

//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
}
<!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>
//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
}
然后,我编写了一个快速测试页面,以了解这是否按预期工作,并允许我随意添加和删除事件处理程序

HTML测试页面如下所示:

//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
}
<!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>
//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
}
测试代码如下所示:

//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
}
<!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>
//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
}
因此,要执行的测试如下所示:

//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
}
<!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>
//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
}
[1] 将单击事件处理程序附加到按钮#1

[2] 测试查看当我单击按钮时是否调用了事件处理程序

[3] 测试通过后,单击按钮#2并调用附加到按钮#1的事件处理程序,该程序将删除附加到按钮#1的旧事件处理程序,然后将其替换为新事件处理程序

步骤[1]和[2]工作正常。事件处理程序被附加,并在我单击按钮时调用

问题在于步骤[3]

即使我保存了对MakeEventHandler()生成的函数的引用,特别是为了在步骤[3]中删除该事件侦听器,对removeEventListener()的调用也不会删除该事件侦听器。随后单击按钮#1将启动两个事件侦听器,包括我应该删除的一个

不用说,我发现这种行为令人费解,尽管我仔细地设置了一切,以便我在调用removeEventListener()时指定的函数与我最初使用addEventListener()添加的函数是同一个函数-根据我所阅读的主题文档(包括此线程),为每个调用传递对同一函数的引用应该可以工作,但显然不行

在步骤[1]中,控制台中的测试输出如预期的那样读取:

按钮1初始事件处理程序已触发

在步骤[2]中,代码也会按预期运行,对代码的逐步跟踪表明,代码确实按预期执行

但在步骤[3]中,当第一次点击按钮#1产生所需结果时:

按钮1最终事件处理程序已触发

随后单击按钮#1时会发生什么情况

按钮1初始事件处理程序已触发 按钮1最终事件处理程序已触发

当然,即使最初附加到按钮#1的函数仍然存在于内存中,因为它是在闭包中生成的,它仍然应该与元素的事件侦听器集合分离?为什么它仍然是连接的


或者我遇到了一些奇怪的错误,涉及到在事件侦听器中使用闭包,需要报告吗?

我发现对于windows对象,最后一个参数“true”是必需的。
如果没有捕获标志,删除就不起作用。

这就是我最后要做的,但它在route类中,但不会有太大的区别,我希望事件侦听器不要在每次调用afterModel()时累积,还需要参数和作用域,以便每次都更改模型

export default class iFrameRoute extends Route {

      afterModel(model) {

           this.initFrame = function(event) {  
    
               alert("I am being called");

               window.removeEventListener("message",  this.route.test); 

           }.bind({route: this, data: model});

           window.addEventListener("message",  this.initFrame ); 
       } 
}

我有一个数据分页的系统,这个函数提供了许多信息来创建表和插入新的寄存器,因此,在任何导航中,我必须在add按钮上添加eventlistener,我发现最好的方法是在add eventlistener之前销毁元素并再次创建,这对我来说很好

,但我如何传递参数(此处为event)这就是为什么我使用匿名函数它是通过浏览器传递的。不管你是否单独定义函数。警告:我发现我的方法有什么问题。removeEventListener()方法仅适用于命名函数。它不适用于匿名函数!当我编辑代码以考虑到这一点时,一切都按计划进行。您必须在闭包中定义一个命名函数,并使用闭包传递的参数返回对其实例的引用。执行此操作,removeEventListener()将完美工作。+1 True<代码>绑定(此)
将更改签名。因此,在将
this
绑定到使用函数
bind
API之后,始终将函数分配给
var
,以便相同的
var
可以在
removeListener
中使用。你会看到