Poznajemy kolejne sposoby na dodawanie i usuwanie event listenerów. Do dzieła.
Ok, po pierwsze addEventListener to nie jedyna opcja, aby dodać event. Oto inline event:
<button onclick="btnClick()">Click Me</button>
<script>
function btnClick() {
console.log("Button Clicked")
}
</script>
Nie powinno się tego używać. Ale ok, patent na usunięcie:
<button onclick="btnClick()">Click Me</button>
<script>
function btnClick() {
console.log("Button Clicked")
}
function remove(){
document.querySelector("button").removeAttribute("onclick");
}
</script>
Drugi, też nieidealny sposób na dodawanie eventu (jednego):
<button>Click Me</button>
<script defer>
function btnClick() {
console.log("Button Clicked")
}
let btn = document.querySelector("button");
btn.onclick = btnClick;
</script>
Patent na usunięcie – nadpisanie:
<button>Click Me</button>
<script defer>
function btnClick() {
console.log("Button Clicked")
}
let btn = document.querySelector("button");
btn.onclick = btnClick;
function removeOnclick(){
btn.onclick = function() { return false; };
}
</script>
Patent na usuwanie listenera/listenerów, którym daliśmy signal i abort controller:
const button = document.getElementById('button');
const controller = new AbortController();
const { signal } = controller;
button.addEventListener('click', () => console.log('clicked!'), { signal });
// Remove the listener!
controller.abort();
Można wiele naraz. Można używać funkcji anonimowych. Jak chcemy przez removeListener, to musimy mieć funkcje nazwane, już to robiliśmy poprzednio.
A co jeśli nie mamy nazwanych, ale chcemy rozłączyć wszystkie listenery danego elementu?
Taki kod:
class DOMHelper {
static clearEventListeners(element) {
const clonedElement = element.cloneNode(true);
element.replaceWith(clonedElement);
return clonedElement;
}
}
Kopiujemy element i wstawiamy w miejsce oryginału. Kopiowanie rozłącza listenery. Także listenery dzieci.
A gdybyśmy chcieli rozłączyć tylko listenery elementu, bez rozłączania dzieci? Wtedy musimy wszystkim jego listenerom nadać signal i wyłączyć abort controllerem.
A gdybyśmy chcieli skopiować element, ale razem z listenerami? Cóż, wtedy mamy problem, niektóre przeglądarki pozwalają uzyskać dostęp do przypiętych listenerów do danego elementu, ale generalnie tutaj warto rozważyć dwie opcje:
- Delegacja eventów na elemencie głównym i jakiś sposób rozpoznawania delegowanych po klasie, niezależnie gdzie w obrębie głównego się znajdują
- Zrobić DOM wrapper dla tych elementów (taką warstwę abstrakcji), który dodaje element i eventy, potrafi też skopiować element i ponownie przypiąć eventy trzymane w jakiejś mapie/weakmapie
Tym niemniej to trochę bez sensu kopiować elementy z listenerami, lepiej wykorzystać tag template i komponenty, ale jeżeli chcemy, to jedyną rozsądną opcją jest wrapper, warstwa abstrakcji, która potrafi odtworzyć dodanie event listenerów.