Como posso remover um ouvinte de evento, independentemente de como o retorno de chamada é definido
Durante anos, tive problemas ao tentar remover um ouvinte de evento em JavaScript. Muitas vezes, eu teria que criar uma função independente como manipulador. Mas isso é apenas desleixado e, especialmente com a adição de funções de seta, apenas uma do
Não estou buscando uma solução ONCE. Isso precisa funcionar em todas as situações, independentemente de como o retorno de chamada é definido. E isso precisa ser JS bruto, para que qualquer pessoa possa usá-l
O código a seguir funciona bem, pois a funçãoclickHandler
é uma função única e pode ser usada pelos doaddEventListener
eremoveEventListener
:
Este exemplo foi atualizado para mostrar o que encontrei no passado
const btnTest = document.getElementById('test');
let rel = null;
function clickHandler() {
console.info('Clicked on test');
}
function add() {
if (rel === null) {
rel = btnTest.addEventListener('click', clickHandler);
}
}
function remove() {
btnTest.removeEventListener('click', clickHandler);
}
[...document.querySelectorAll('[cmd]')].forEach(
el => {
const cmd = el.getAttribute('cmd');
if (typeof window[cmd] === 'function') {
el.addEventListener('click', window[cmd]);
}
}
);
<button cmd="add">Add</button>
<button cmd="remove">Remove</button>
<button id="test">Test</button>
Você costumava fazer isso comarguments.callee
:
var el = document.querySelector('#myButton');
el.addEventListener('click', function () {
console.log('clicked');
el.removeEventListener('click', arguments.callee); //<-- will not work
});
<button id="myButton">Click</button>
Mas a função de seta não funciona:
var el = document.querySelector('#myButton');
el.addEventListener('click', () => {
console.log('clicked');
el.removeEventListener('click', arguments.callee); //<-- will not work
});
<button id="myButton">Click</button>
Existe uma maneira melhor?
ATUALIZA
Conforme declarado por @Jonas Wilms desta maneira, funcionará:
var el = document.querySelector('#myButton');
el.addEventListener('click', function handler() {
console.log('clicked');
el.removeEventListener('click', handler); //<-- will work
});
<button id="myButton">Click</button>
A não ser qu você precisa usar a ligação:
var obj = {
setup() {
var el = document.querySelector('#myButton');
el.addEventListener('click', (function handler() {
console.log('clicked', Object.keys(this));
el.removeEventListener('click', handler); //<-- will work
}).bind(this));
}
}
obj.setup();
<button id="myButton">Click</button>
O problema é que existem muitas maneiras de fornecer um manipulador de eventos para oaddEventListener
unção @ e seu código pode quebrar se a maneira como você passar na função for alterada em um refato