Javascript removeEventListener ne fonctionne pas

j'ai le code suivant pour ajouter eventListener

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

Il fonctionne correctement comme prévu..Plus tard, dans une autre fonction, j'ai essayé d'enlever l'écouteur d'événement en utilisant le code suivant

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

mais l'écouteur Pair n'est pas supprimé..Pourquoi est-il passe?Est-il un problème avec mon removeEventListener()? Note: ici la zone est quelque chose comme document.getElementById ('myId')

35
demandé sur Jinu Joseph Daniel 2012-05-04 10:51:05

7 réponses

c'est parce que deux fonctions anonymes sont des fonctions complètement différentes. Votre n'est pas une référence à l'objet de fonction qui était précédemment attaché.

function foo(event) {
              app.addSpot(event.clientX,event.clientY);
              app.addFlag = 1;
          }
 area.addEventListener('click',foo,true);
 area.removeEventListener('click',foo,true);
58
répondu duri 2012-05-04 06:56:58

vous créez deux fonctions différentes dans les deux appels. Ainsi, la deuxième fonction n'est pas liée de quelque façon à la première et le moteur est capable de supprimer la fonction. Utilisez plutôt un identifiant commun pour la fonction.

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

plus tard, vous pouvez alors supprimer le gestionnaire en appelant

area.removeEventListener('click', handler,true);
2
répondu Sirko 2012-05-04 06:57:54

je trouve que pour l'objet windows, le dernier param "vrai" est nécessaire. Le retrait ne fonctionne pas s'il n'y a pas de drapeau de capture.

1
répondu Slavik 2018-06-05 14:44:34

définissez d'abord votre gestionnaire D'événements,

et

area.addEventListener('click',handler);
area.removeEventListener('click',handler);
0
répondu neohope 2012-05-04 06:57:05

pour le supprimer, stockez la fonction dans une variable ou utilisez simplement une fonction nommée et passez cette fonction à removeEventListener appel:

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

area.addEventListener('click', areaClicked, true);
// ...
area.removeEventListener('click', areaClicked, true);
0
répondu ThiefMaster 2015-05-21 17:53:58

Si vous souhaitez passer des variables locales à la fonction appelée par l'écouteur d'événement, vous pouvez définir la fonction à l'intérieur de la fonction (pour obtenir les variables locales) et de passer le nom de la fonction dans la fonction elle-même. Par exemple, commençons à l'intérieur de la fonction qui ajoute l'écouteur d'événements avec app comme variable locale. Vous écririez une fonction à l'intérieur de cette fonction comme,

function yourFunction () {
    var app;

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

    area.addEventListener('click', waitListen, true);
}

alors vous avez ce qu'il faut pour l'enlever quand waitexécute est appelé.

function waitExecute (app, waitListen) {
    ... // other code
    area.removeEventListener('click', waitListen, true);
}
0
répondu VectorVortec 2016-03-22 21:01:30

j'ai rencontré un problème avec removeEventListener() qui doit être expliqué.

je voulais pouvoir passer des paramètres aux écouteurs d'événements, donc j'ai écrit une fonction pour générer l'écouteur d'événements, qui à son tour retourne une deuxième fonction, qui appelle mon auditeur d'événements prévu comme un rappel.

La bibliothèque complète fichier est comme suit:

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

puis j'ai écrit une page test rapide pour savoir si cela a fonctionné comme prévu, et m'a permis d'ajouter et de supprimer les gestionnaires d'événements.

Le code HTML de la page de test est comme suit:

<!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>

Pour être complet, j'utilise la suite simple fichier 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! */

}

le code de test est le suivant:

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

ainsi, le test à effectuer est le suivant:

[1] Attacher un gestionnaire d'événements click pour le Bouton #1;

[2] Test pour voir si le gestionnaire d'événement est invoqué lorsque je clique sur le bouton;

[3] Une fois que ce test est passé, cliquez sur le bouton #2, et invoquez le gestionnaire d'événements qui y est attaché, ce qui supprime l'ancien gestionnaire d'événements attaché au bouton #1, puis le remplace par un nouveau gestionnaire d'événements.

les Étapes [1] et [2], beau travail. Le gestionnaire d'événements est attaché et invoqué chaque fois que je clique sur le bouton.

le problème est avec L'Étape [3].

même si j'enregistre une référence à la fonction générée par MakeEventHandler(), spécifiquement dans le but de supprimer cet écouteur d'événements dans l'Étape [3], l'appel à removeEventListener() ne supprime PAS l'écouteur d'événement. Le clic suivant sur le bouton #1 déclenche les deux écouteurs d'événements, y compris celui que j'ai soi-disant supprimé!

inutile de dire que ce comportement me laisse perplexe, malgré le fait que j'ai soigneusement tout mis en place pour que la fonction que je spécifie dans l'appel à removeEventListener() soit la même que celle que j'ai ajoutée initialement avec addEventListener() - selon la documentation sur le sujet J'ai lu (y compris ce fil), de passer une référence à la même fonction pour chaque appel devrait travail, mais n'est manifestement pas le cas.

À l'Étape [1], le test de sortie dans la console lit, comme prévu:

bouton 1 déclenchement du gestionnaire d'événements initial

le code est également exécuté, comme prévu, à L'Étape [2], et une trace étape par étape du code révèle qu'en effet, le code est exécuté comme prévu.

mais à l'Étape [3], alors que les premier cliquez sur le bouton #1 pour obtenir le résultat désiré:

bouton 1 déclencheur de l'événement final

ce qui se passe lorsque le Bouton #1 est cliqué sur par la suite c'est:

bouton 1 déclenchement du gestionnaire d'événements initial Bouton 1 déclencheur de l'événement final

sûrement, même si la fonction initialement attachée au bouton #1 persiste toujours en mémoire, parce qu'elle a-t-il été généré dans le cadre d'une fermeture, devrait-il tout de même être détaché de la collection des écouteurs d'événements pour l'élément? Pourquoi est-il connecté?

ou Ai-je rencontré un bug étrange impliquant l'utilisation de fermetures avec des écouteurs d'événements, qui doit être signalé?

0
répondu David Edwards 2018-01-18 11:00:18