web-dev-qa-db-fra.com

Espace de noms du gestionnaire d'événements dans Vanilla JavaScript

Je connais les espaces de noms dans les gestionnaires d'événements de jQuery. Je peux ajouter un gestionnaire d'événements dans un espace de noms spécifique:

$('#id').on('click.namespace', _handlerFunction);

Et puis je peux supprimer tous les gestionnaires d'événements dans cet espace de noms:

$('#id').off('.namespace');

L'avantage ici est que je ne peux supprimer que les événements de cet espace de noms, pas les événements ajoutés par l'utilisateur/supplémentaires qui doivent être conservés.

Quelqu'un a-t-il des conseils sur la façon dont je ne peux pas utiliser jQuery, mais obtenir un résultat similaire?

34
Tyler Conover

Je pense que vous recherchez addEventListener et removeEventListener . Vous pouvez également définir des événements personnalisés et les déclencher à l'aide de dispatchEvent .

Cependant, pour supprimer un écouteur d'événement, vous devrez conserver une référence à la fonction d'événement pour supprimer uniquement la fonction que vous souhaitez supprimer au lieu d'effacer tout l'événement.

10
Will P.

Pour tous ceux qui recherchent toujours cela, j'ai fini par faire un singleton d'aide qui garde une trace des références de fonction pour moi.

class EventClass {
  constructor() {
    this.functionMap = {};
  }

  addEventListener(event, func) {
    this.functionMap[event] = func;
    document.addEventListener(event.split('.')[0], this.functionMap[event]);
  }

  removeEventListener(event) {
    document.removeEventListener(event.split('.')[0], this.functionMap[event]);
    delete this.functionMap[event];
  }
}

export const Event = new EventClass();

Ensuite, importez simplement Event et utilisez comme:

Event.addEventListener('keydown.doop', () => console.log("Doop"));
Event.addEventListener('keydown.wap', () => console.log("Wap"));
Event.removeEventListener('keydown.doop');
// keydown.wap is still bound
28
Andrew

Dans cette solution, j'ai étendu le DOM pour avoir des méthodes on et off avec la possibilité d'utiliser l'espace de noms des événements:

var events = {
  on(event, cb, opts){
    if( !this.namespaces ) // save the namespaces on the DOM element itself
      this.namespaces = {};

    this.namespaces[event] = cb;
    var options = opts || false;
    
    this.addEventListener(event.split('.')[0], cb, options);
    return this;
  },
  off(event) {
    this.removeEventListener(event.split('.')[0], this.namespaces[event]);
    delete this.namespaces[event];
    return this;
  }
}

// Extend the DOM with these above custom methods
window.on = Element.prototype.on = events.on;
window.off = Element.prototype.off = events.off;


window
  .on('mousedown.foo', ()=> console.log("namespaced event will be removed after 3s"))
  .on('mousedown.bar', ()=> console.log("event will NOT be removed"))
  .on('mousedown.baz', ()=> console.log("event will fire once"), {once: true});

// after 3 seconds remove the event with `foo` namespace
setTimeout(function(){
    window.off('mousedown.foo')
}, 3000)
Click anywhere 
16
vsync