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.
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'); })
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; }
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(); });
5 Réponses :
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
Avez-vous essayé cela?
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);
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.
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);
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
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);
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) });
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