Tengo un problema muy "simple" de vanillaJS. ¿Cómo puedo eliminar el detector de eventos en bucle dentro de una función de curry? Este es solo un ejemplo de mi solución actual en la que realmente necesito múltiples parámetros para el oyente. Sospecho que el detector de eventos no se elimina debido a una devolución de llamada anónima si tengo razón. ¿Cómo puedo arreglar esto? Ejemplo aquí https://codepen.io/shnigi/pen/wvPwqVR
const setEventListener = (buttons) => (event) => { const buttonValue = event.target.value; console.log('Eventlistener exists', buttonValue) buttons.forEach(button => button.removeEventListener('click', setEventListener)); }; const buttons = document.querySelectorAll('button'); buttons.forEach(button => button.addEventListener('click', setEventListener(buttons))); // Works as expected, listener is named const testbutton = document.getElementById('kek'); const testListener = () => { console.log('I show up only once'); testbutton.removeEventListener('click', testListener); }; testbutton.addEventListener('click', testListener); <button value="1">press me</button> <button value="2">press me</button> <button id="kek">eventlistener removed on click</button>Sospecho que el detector de eventos no se elimina debido a una devolución de llamada anónima si tengo razón.
Si, eso es un problema. Por lo tanto, debe asignar una función anónima a la variable y usarla para eliminar el detector de eventos.
Aquí hay un código de muestra para usted.
const setEventListener = (buttons: NodeList) => { const returnedFunc = (event: Event) => { const buttonValue = (event.target as HTMLButtonElement).value; console.log('Eventlistener exists', buttonValue) buttons.forEach(button => button.removeEventListener('click', returnedFunc)); }; return returnedFunc; }; const buttons: Nodelist = document.querySelectorAll('button'); buttons.forEach(button => button.addEventListener('click', setEventListener(buttons))); // Works as expected, listener is named const testbutton = document.getElementById('kek'); const testListener = () => { console.log('I show up only once'); testbutton.removeEventListener('click', testListener); }; testbutton.addEventListener('click', testListener);Si no le importa la compatibilidad con Internet Explorer, puede eliminar los detectores de eventos anónimos de una manera más elegante utilizando AbortController . Pase la opción de signal a addEventListener() y llame al método abort() de AbortController cuando desee eliminar el detector de eventos:
var listenersRemover = new AbortController(); button.addEventListener('click', callback, {signal: listenersRemover.signal})); listenersRemover.abort(); Note : debe "rearmar" el controlador de cancelación para usar la misma señal para las nuevas llamadas addEventListener() . Simplemente inicialícelo nuevamente con new AbortController() .
var listenersRemover = new AbortController(); const setEventListener = (buttons) => (event) => { const buttonValue = event.target.value; console.log('Eventlistener exists', buttonValue) // buttons.forEach(button => button.removeEventListener('click', setEventListener)); }; const buttons = document.querySelectorAll('button'); buttons.forEach(button => button.addEventListener('click', setEventListener(buttons), {signal: listenersRemover.signal})); // Works as expected, listener is named const testbutton = document.getElementById('kek'); const testListener = () => { console.log('I show up only once'); //testbutton.removeEventListener('click', testListener); listenersRemover.abort(); }; testbutton.addEventListener('click', testListener, {signal: listenersRemover.signal}); <button value="1">press me</button> <button value="2">press me</button> <button id="kek">eventlistener removed on click</button>