Javascript removeEventListener non funziona

Ho il seguente codice per aggiungere eventListener

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

Funziona correttamente come previsto. Più in un’altra funzione ho provato a rimuovere il listener di eventi usando il seguente codice

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

Ma l’ascoltatore pari non viene rimosso. Perché sta accadendo? C’è qualche problema con il mio removeEventListener ()? Nota: qui l’area è qualcosa come document.getElementById (‘myId’)

Questo perché le due funzioni anonime sono funzioni completamente diverse. L’argomento removeEventListener non è un riferimento all’object funzione precedentemente collegato.

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

Stai creando due diverse funzioni in entrambe le chiamate. Quindi la seconda funzione non si riferisce in alcun modo al primo e il motore è in grado di rimuovere la funzione. Utilizzare invece un identificatore comune per la funzione.

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

in seguito è ansible rimuovere il gestore chiamando

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

Trovo che per l’object Windows, è richiesto l’ultimo parametro “true”. La rimozione non funziona se non c’è alcuna bandiera di cattura.

definire prima il gestore eventi,

e poi

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

Per rimuoverlo, memorizzare la funzione in una variabile o semplicemente utilizzare una funzione con nome e passare tale funzione alla chiamata removeEventListener :

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

Se si desidera passare variabili locali alla funzione chiamata dal listener di eventi, è ansible definire la funzione all’interno della funzione (per ottenere le variabili locali) e passare il nome della funzione nella funzione stessa. Ad esempio, iniziamo all’interno della funzione che aggiunge il listener di eventi con app come variabile locale. Dovresti scrivere una funzione all’interno di questa funzione come,

 function yourFunction () { var app; function waitListen () { waitExecute(app, waitListen); } area.addEventListener('click', waitListen, true); } 

Quindi hai quello che ti serve per rimuoverlo quando viene chiamatoExecute.

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

Ho riscontrato un problema con removeEventListener () che deve essere spiegato.

Volevo essere in grado di passare parametri agli ascoltatori di eventi, quindi ho scritto una funzione per generare il listener di eventi, che a sua volta restituisce una seconda funzione, che chiama il listener di eventi previsto come callback.

Il file della libreria completo è il seguente:

 //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 } 

Poi ho scritto una pagina di test veloce per scoprire se questo ha funzionato come previsto, e mi ha permesso di aggiungere E rimuovere i gestori di eventi a volontà.

La pagina di test HTML è la seguente:

                

Per completezza, utilizzo anche il seguente semplice file CSS:

 /* NewEventTest.css */ /* Define standard display settings classs 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! */ } 

Il codice di prova è il seguente:

 //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 } 

Quindi, il test da eseguire è il seguente:

[1] Allega un gestore di eventi click al pulsante n. 1;

[2] Verificare se il gestore eventi viene richiamato quando faccio clic sul pulsante;

[3] Una volta superato il test, fai clic sul pulsante n. 2 e richiama il gestore eventi ad esso associato, che rimuove il vecchio gestore eventi collegato al pulsante n. 1, quindi lo sostituisce con un nuovo gestore eventi.

I passaggi [1] e [2] funzionano bene. Il gestore di eventi è allegato e richiamato ogni volta che clicco sul pulsante.

Il problema è con Step [3].

Anche se salvi un riferimento alla funzione generata da MakeEventHandler (), in particolare allo scopo di rimuovere quel listener di eventi in Step [3], la chiamata a removeEventListener () NON rimuove il listener di eventi. Il clic successivo sul pulsante 1 triggers tutti gli ascoltatori di eventi, incluso quello che presumibilmente ho rimosso!

Inutile dire che questo comportamento lo trova sconcertante, malgrado abbia accuratamente impostato tutto in modo tale che la funzione che ho specificato nella chiamata a removeEventListener () sia la stessa stessa funzione che ho aggiunto inizialmente con addEventListener () – secondo tutta la documentazione sull’argomento I Ho letto (incluso questo thread), il passaggio di un riferimento alla stessa funzione per ogni chiamata dovrebbe funzionare, ma chiaramente non lo è.

Al Passo [1], l’output di test nella console viene letto, come previsto:

Attivato il gestore di eventi iniziale del pulsante 1

Il codice viene anche eseguito, come previsto, nel passaggio [2], e una traccia del codice passo per passo rivela che, in effetti, il codice viene eseguito come previsto.

Ma nel passaggio [3], mentre il primo clic sul pulsante n. 1 produce il risultato desiderato:

Pulsante 1 gestore di eventi finale triggersto

cosa succede quando il pulsante # 1 viene cliccato in seguito è questo:

Pulsante 1 gestore eventi iniziale triggersto Gestore evento finale Button 1 triggersto

Sicuramente, anche se la funzione inizialmente collegata al pulsante n. 1 persiste ancora in memoria, perché è stata generata all’interno di una chiusura, dovrebbe comunque essere staccato dalla raccolta listener di eventi per l’elemento? Perché è ancora connesso?

O ho incontrato qualche strano bug che riguarda l’utilizzo di chiusure con listener di eventi, che deve essere segnalato?