web-dev-qa-db-fra.com

removeEventListener sur les fonctions anonymes en JavaScript

J'ai un objet qui contient des méthodes. Ces méthodes sont placées dans l'objet à l'intérieur d'une fonction anonyme. Cela ressemble à ceci:

var t = {};
window.document.addEventListener("keydown", function(e) {
    t.scroll = function(x, y) {
        window.scrollBy(x, y);
    };
    t.scrollTo = function(x, y) {
        window.scrollTo(x, y);
    };
});  

(il y a beaucoup plus de code, mais cela suffit pour montrer le problème)

Maintenant, je veux arrêter l'écouteur d'événements dans certains cas. Par conséquent, j'essaie de supprimer removeEventListener mais je ne vois pas comment faire. J'ai lu dans d'autres questions qu'il n'est pas possible d'appeler removeEventListener sur des fonctions anonymes, mais est-ce également le cas dans cette situation?

J'ai une méthode créée à l'intérieur de la fonction anonyme et j'ai donc pensé que c'était possible. Ressemble à ça:

t.disable = function() {
    window.document.removeEventListener("keydown", this, false);
}

Pourquoi je ne peux pas faire ça?

Y a-t-il un autre (bon) moyen de faire cela?

Informations sur les bonus cela ne doit fonctionner que dans Safari, d’où le support manquant, c’est-à-dire.

75
bitkid

Je crois que c'est le but d'une fonction anonyme, il manque un nom ou un moyen de s'y référer.

Si j'étais vous, je créerais simplement une fonction nommée ou la placerais dans une variable afin que vous ayez une référence.

var t = {};
var handler = function(e) {
    t.scroll = function(x, y) {
        window.scrollBy(x, y);
    };
    t.scrollTo = function(x, y) {
        window.scrollTo(x, y);
    };
};
window.document.addEventListener("keydown", handler);

Vous pouvez ensuite l'enlever par

window.document.removeEventListener("keydown", handler);   
58
Adam Heath

si vous êtes dans la fonction réelle, vous pouvez utiliser arguments.callee comme référence à la fonction. un péché:

button.addEventListener('click', function() {
      ///this will execute only once
      alert('only once!');
      this.removeEventListener('click', arguments.callee);
});

EDIT: Cela ne fonctionnera pas si vous travaillez en mode strict ("use strict";)

85
Otto Nascarella

Une version de la solution de Otto Nascarella qui fonctionne en mode strict est la suivante:

button.addEventListener('click', function handler() {
      ///this will execute only once
      alert('only once!');
      this.removeEventListener('click', handler);
});
34
Melle
window.document.removeEventListener("keydown", getEventListeners(window.document.keydown[0].listener));  

Peut-être plusieurs fonctions anonymes, keydown [1]

8
user3519897

Une option pas si anonyme

element.funky = function() {
    console.log("Click!");
};
element.funky.type = "click";
element.funky.capt = false;
element.addEventListener(element.funky.type, element.funky, element.funky.capt);
// blah blah blah
element.removeEventListener(element.funky.type, element.funky, element.funky.capt);

Depuis que j'ai reçu les commentaires d'Andy (très bien, mais comme pour de nombreux exemples, je souhaitais montrer une expansion contextuelle de l'idée}, voici une exposition {moins compliquée}:

<script id="konami" type="text/javascript" async>
    var konami = {
        ptrn: "38,38,40,40,37,39,37,39,66,65",
        kl: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
    };
    document.body.addEventListener( "keyup", function knm ( evt ) {
        konami.kl = konami.kl.slice( -9 );
        konami.kl.Push( evt.keyCode );
        if ( konami.ptrn === konami.kl.join() ) {
            evt.target.removeEventListener( "keyup", knm, false );

            /* Although at this point we wish to remove a listener
               we could easily have had multiple "keyup" listeners
               each triggering different functions, so we MUST
               say which function we no longer wish to trigger
               rather than which listener we wish to remove.

               Normal scoping will apply to where we can mention this function
               and thus, where we can remove the listener set to trigger it. */

            document.body.classList.add( "konami" );
        }
    }, false );
    document.body.removeChild( document.getElementById( "konami" ) );
</script>

Cela permet une structure de fonction effectivement anonyme, évite l’utilisation du pratiquement obsolète appelé , et permet une suppression aisée.

Incidemment: la suppression de l'élément de script immédiatement après le réglage de l'auditeur est un truc sympa pour cacher du code, on préférerait ne pas être évident pour les regards indisques (gâcherait la surprise};

Donc, la méthode (plus simplement) est la suivante:

element.addEventListener( action, function name () {
    doSomething();
    element.removeEventListener( action, name, capture );
}, capture );
2
Fred Gandt

Ce n’est pas idéal car cela supprime tout, mais pourrait répondre à vos besoins:

z = document.querySelector('video');
z.parentNode.replaceChild(z.cloneNode(1), z);

Le clonage d'un nœud copie tous ses attributs et leurs valeurs, y compris auditeurs intrinsèques (en ligne). Il ne copie pas les écouteurs d'événements ajoutés à l'aide de addEventListener ()

Node.cloneNode ()

2
user4427511

Pour donner une approche plus actuelle à ceci:

//one-time fire
element.addEventListener('mousedown', {
  handleEvent: function (evt) {
    element.removeEventListener(evt.type, this, false);
  }
}, false);
1
Jonatas Walker

JavaScript : addEventListenerla méthode enregistre l'écouteur spécifié dans l'objet EventTarget (Element | document | Window) sur lequel elle est appelée.

EventTarget. addEventListener ( event_type , handler_function, Bubbling | Capture );

Souris, clavier événements Exemple de test dans WebConsole:

var keyboard = function(e) {
    console.log('Key_Down Code : ' + e.keyCode);
};
var mouseSimple = function(e) {
    var element = e.srcElement || e.target;
    var tagName = element.tagName || element.relatedTarget;
    console.log('Mouse Over TagName : ' + tagName);    
};
var  mouseComplex = function(e) {
    console.log('Mouse Click Code : ' + e.button);
} 

window.document.addEventListener('keydown',   keyboard,      false);
window.document.addEventListener('mouseover', mouseSimple,   false);
window.document.addEventListener('click',     mouseComplex,  false);

removeEventListenerla méthode supprime l'écouteur d'événement précédemment enregistré avec EventTarget.addEventListener ().

window.document.removeEventListener('keydown',   keyboard,     false);
window.document.removeEventListener('mouseover', mouseSimple,  false);
window.document.removeEventListener('click',     mouseComplex, false);

puis-je utiliser

1
Yash

dans les navigateurs modernes, vous pouvez:.

button.addEventListener( 'click', () => {
    alert( 'only once!' );
}, { once: true } );

https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Parameters

1
shunryu111

Je suis tombé sur le même problème et c'était la meilleure solution que je pouvais obtenir:

/*Adding the event listener (the 'mousemove' event, in this specific case)*/
element.onmousemove = function(event) {
    /*do your stuff*/
};
/*Removing the event listener*/
element.onmousemove = null;

N'oubliez pas que je n'ai testé cela que pour l'élément window et pour l'événement 'mousemove'; il pourrait donc y avoir des problèmes avec cette approche.

0
Gark Garcia