0
votes

Js: supprimer ou désactiver les écouteurs d'événements ajoutés précédemment d'un certain événement

codepen

Prenons l'exemple suivant (identique à codepen)

/* html element selector */

// element: one event maps to one handler
function elemental(el){
  el.oneEventListener = (event, func) => {
    if(el.lastEventListener == null){
      el.lastEventListener = {};
    }
    if(el.lastEventListener[event] != null){
      el.removeEventListener(event, el.lastEventListener[event]);
    }
    el.addEventListener(event, func);
    el.lastEventListener[event] = func;
  }
  return el;
}

// querySelector -> element
function proxy(el){
  return elemental(el);
}

// querySelectorAll -> NodeList
function proxyAll(el){
  el.forEach(ele=>{
    ele = elemental(ele);
  });
  return el;
}

/*
once proxy is implemented, by oneEventListener, 
only one event listener of particular type will exist on that element,
if you call addEventListener, proxy doesn't interfer it.
which the eventlistener added will work normally.
*/

// proxy query selector
const pqs = function(str){
  return proxy(document.querySelector(str));
}

// proxy query selector all
const pqsa = function(str){
  return proxyAll(document.querySelectorAll(str));
}
<div></div>
div{
  width: 200px;
  height: 200px;
  background: red;
}

la sortie attendue est b ;

Dans mon code d'origine, j'ai plus d'un gestionnaire d'événements, tels que click , mousemove , etc. y a-t-il un moyen de supprimer tous les écouteurs d'événements d'un événement particulier que j'ai précédemment ajouté?

Par exemple, au début, click sur mon bouton déclenche la function A ; au milieu, je considère avoir besoin d'un changement fonctionnel, donc au lieu de déclencher la function A , je veux la function B , et seulement la function B

J'ai lu:

mais cela n'a pas beaucoup aidé. Merci de votre aide.


mise à jour

Pour être plus précis, existe-t-il un moyen d'empêcher les écouteurs d'événements précédemment ajoutés de click dans la nouvelle fonction ajoutée, par exemple:

// add a new method to element, oneEventListener, 
// for a speficified event type, only save and execute last add handler

function elemental(el){
    el.oneEventListener = (event, func) => {
        if(el.lastEventListener == null){
          el.lastEventListener = {};
        }
        if(el.lastEventListener[event] != null){
          el.removeEventListener(event, el.lastEventListener[event]);
        }
        el.addEventListener(event, func);
        el.lastEventListener[event] = func;
    }
    return el;
}

// eventhandler singleton, support querySelector, getElementById, etc, even support querySelectorAll and getElementsByClassName
function proxy(el) {
  if(!(el instanceof NodeList)){
    return elemental(el);
  }else{
    el.forEach(ele=>{
      ele = elemental(ele);
    });
    return el;
  }
}

const div = proxy(document.querySelector('div'));
// const div = document.querySelector('div');

div.oneEventListener('click', e=>{
    console.log('a');
})

div.oneEventListener('click', e=>{
    console.log('b');
})

div.oneEventListener('click', ()=>{
    console.log('c');
})

div.oneEventListener('mouseover', ()=>{
    console.log('aa');
})

div.oneEventListener('mouseover', ()=>{
    console.log('bb');
})

div.oneEventListener('mouseover', ()=>{
    console.log('cc');
})

Solution

Grâce à @Kayac, nous avons résolu ceci:

my_button.addEventListener('click', ()=>{
    console.log('a');
});

my_button.addEventListener('click', ()=>{
    // remove all previously added click handlers 
    console.log('b');
});

<div></div>
div{
  width: 200px;
  height: 200px;
  background: red;
}

Mise à jour

Pour les visiteurs, si vous recherchez un sélecteur html pour vous permettre d'effectuer un singleton sur l'écouteur d'événements, le code suivant est optimisé pour les performances.

const div = document.querySelector('div');

function a(){
  console.log('a');
}

function b(){
  console.log('b');
}

div.addEventListener('click', e=>{
  a();
});

div.addEventListener('click', e=>{
  // I don't want all previous added event handlers to work, is there a way to remove it?
  b();
});


0 commentaires

5 Réponses :


1
votes

Vous devez supprimer l'écouteur d'événement précédent par référence: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener

essaye ça:

const div = document.querySelector('div');

function a(){
  console.log('a');
}

function b(){
  console.log('b');
}

div.addEventListener('click', a);

// condition for changing event listener
if (true) {
    div.removeEventListener('click', a);
}

div.addEventListener('click', b);

Cela ne devrait exécuter que b


0 commentaires

1
votes

Avez-vous essayé cela?

removeEventListener

Il supprime un événement "click" qui a été attaché avec la méthode addEventListener ():

Exemple

// Attach an event handler to <div>
document.getElementById("myDIV").addEventListener("click", myFunction);

// Remove the event handler from <div>
document.getElementById("myDIV").removeEventListener("click", myFunction);


2 commentaires

puis-je appeler cette méthode sans le deuxième paramètre? Je veux me débarrasser de tous les gestionnaires de click précédents.


@Weilory non, vous ne pouvez pas supprimer toutes les fonctions précédemment attachées.



1
votes

Essaye ça

function a() {
  console.log("a");
}

function b() {
  console.log("b");
}

function proxy(el) {
  const map = {};

  return {
    addEventListener: (event, func) => {
      !map[event] && el.addEventListener(event, () => map[event]());

      map[event] = func;
    }
  };
}

const div = proxy(document.querySelector("div"));

div.addEventListener("click", a);
div.addEventListener("click", b);


2 commentaires

Merci, est-ce qu'ils peuvent accéder aux attributs de l'élément avec cette méthode? par exemple le style de certains éléments et context2d du canevas.


Essayez ce codeandbox.io/s/musing-kilby-6fil3



1
votes

J'ai bien peur que vous deviez suivre vous-même les événements que vous attachez à un élément en utilisant addEventListener . Il n'y a pas de méthode intégrée pour les interroger. Pour supprimer correctement un événement à l'aide de removeEventListener , il doit avoir la même signature que l'appel à addEventListener.

Cela se fait en utilisant une fonction nommée au lieu d'une fonction anonyme.

Par exemple:

<button id="myButton">
click me
</button>
<button id="myButton2">
attach new listener
</button>
var myButton = document.getElementById("myButton");
var myButton2 = document.getElementById("myButton2");

function a() {
  console.log("function a");
}

function b() {
  console.log("function b");
}

function changeFunction() {
  myButton.removeEventListener('click', a);
  myButton.addEventListener('click', b);
}
myButton.addEventListener('click', a);
myButton2.addEventListener('click', changeFunction);


0 commentaires

1
votes

Il n'y a pas de moyen simple de le faire.

Cependant, si vous contrôlez tous les ajouts et suppressions d'écouteurs, vous pouvez collecter les écouteurs et tout supprimer, comme ceci:

<div id="div"></div>
#div{
  width: 200px;
  height: 200px;
  background: red;
}
const elements = new WeakMap

function customAddEventListener(elem, event, fn){
  elem.addEventListener(event, fn)

  if(!elements.has(elem)) elements.set(elem, Object.create(null))
  const events = elements.get(elem)
  if(!(event in events)) events[event] = new Set
  const fns = events[event]

  fns.add(fn)
}
function customRemoveEventListener(elem, event, fn){
  elem.removeEventListener(event, fn)

  if(!elements.has(elem)) return
  const events = elements.get(elem)
  if(!event in events) return
  const fns = events[event]

  fns.delete(fn)

  if(!fns.size) delete events[event]
  if(!Reflect.ownKeys(events).length) elements.delete(elem)
}

function removeAllEventListeners(elem, event){

  if(!elements.has(elem)) return
  const events = elements.get(elem)
  if(!event in events) return
  const fns = events[event]

  for(const fn of fns)
    elem.removeEventListener(event, fn)

  delete events[event]
  if(!Reflect.ownKeys(events).length) elements.delete(elem)
}


const div = document.querySelector('#div');

function a(){
  console.log('a');
}

function b(){
  console.log('b');
}

customAddEventListener(div, 'click', e=>{
  a();
});

customAddEventListener(div, 'click', function fn(e){
  b();
  removeAllEventListeners(div, 'click')
  //add this one back
  customAddEventListener(div, 'click', fn)
});


2 commentaires

Appréciez-le. les écouteurs d'événements ajoutés précédemment ont la priorité sur les nouveaux écouteurs, quelle function A sera exécutée avant le nouvel event listener avant la function B , c'est la partie ennuyeuse.


@Weilory Est-ce un problème? Ajoutez-les dans l'ordre inverse