Sunteți pe pagina 1din 13

Lecția 6

Eliminarea ascultătorilor de evenimente

Pentru a elimina un ascultător de evenimente, folosim metoda .removeEventListener(). Sună


destul de simplu, nu? Cu toate acestea, înainte de a ne uita peste metoda .removeEventListener(),
trebuie să facem o scurtă trecere în revistă a egalității obiectelor. Pare un salt ciudat, dar va avea
sens în doar o clipă.

Obiecte egale în JavaScript

Egalitatea este o sarcină obișnuită în majoritatea limbajelor de programare, dar în JavaScript, poate
fi puțin dificil, deoarece JavaScript va încerca să convertească elementele comparate în același tip.
(de ex. șir, număr,). JavaScript are operatorul de egalitate dublă == ( ) care va permite compararea
indiferent de tipul variabilei. De asemenea, are simbolul triplu egalitate === ( ) care va împiedica
constrângerea tipului atunci când se compară.

Sperăm că toate acestea sunt recenzii. Dar să vorbim despre doar egalitate obiect, care include
obiecte, tablouri, și funcții. Încercați să dați un comentariu acestei soluții:

Resursă: https://www.youtube.com/watch?v=A1hfTM8pagg&feature=emb_logo.

Chiar și dacă 2 obiecte arată la fel, acest lucru nu înseamnă că sunt egale. Adică aceeași informație
nu înseamnă egalitate. Atunci când analizăm obiectele JavaScript trebuie să vedem dacă acestea
sunt 2 obiecte diferite sau sunt nume diferite atribuite aceluiași obiect.
R: Acesta este același lucru ca { name: 'Richard' } === { name: 'Richard' }; ambele myFunction sunt
funcții diferite. Arată la fel, dar sunt entități distincte.
R: Ambele funcții myFunction se referă la aceeași funcție quiz exactă.

Ok, de ce a trebuit să analizăm egalitatea dintre aceste obiecte / funcții? Motivul este că metoda
.removeEventListener() necesită să îi transmiteți aceeași funcție de ascultător exactă ca cea către
care ați trecut .addEventListener().

Să vedem un pseudo-cod pentru .removeEventListener():

Deci, un ascultător de evenimente are nevoie de trei lucruri:

1. o țintă de eveniment - aceasta se numește target

2. tipul evenimentului de ascultat

3. funcția de eliminat - se numește ascultător

Amintiți-vă, funcția ascultător trebuie să fie exact aceeași funcție ca cea utilizată în apelul
.addEventListener()... nu doar o funcție identică. Să ne uităm la câteva exemple.

Acest cod va adăuga cu succes și apoi va elimina un ascultător de evenimente:


Acum, de ce funcționează acest lucru? Funcționează deoarece ambele .addEventListener()și
.removeEventListener:

- au aceeași țintă
- au același tip
- și treceți exact același ascultător

Acum să vedem un exemplu care nu ar funcționa ( nu elimină ascultătorul de evenimente):

Acest cod nu elimina cu succes ascultător eveniment. Din nou, de ce nu funcționează?

- ambele .addEventListener() și .removeEventListener au aceeași țintă


- ambele .addEventListener() și .removeEventListener au același tip

.addEventListener() și .removeEventListenerau propriile lor funcții distincte de ascultare ... nu se


referă exact la aceeași funcție ( acesta este motivul pentru care eliminarea ascultătorului de
evenimente eșuează!)
Când am scris:

A doua oară, am creat de fapt o funcție complet nouă, care a fost stocată într-o locație complet nouă
în memorie! S-ar putea să arate la fel și să facă același lucru, dar asta nu le face la fel. Imaginați-vă
un scenariu în care vedeți două case care arată exact la fel. În timp ce casele ar putea arăta la fel,
adresele lor sunt diferite! Exact asta tocmai s-a întâmplat în exemplul nostru anterior.

R: Deoarece ambele .addEventListener()și .removeEventListener oferă propria lor funcție


respondToSubmit()și nu se referă la aceeași funcție, eliminarea ascultătorului de evenimente
eșuează și <form> va avea în continuare un ascultător de evenimente atașat la acesta.

Accesați link-ul de mai jos și vedeți cum asta funcționează în browser.

https://www.youtube.com/watch?v=chX2ZNzGXZo&feature=emb_logo

Ce urmeaza?

Acum, că am aflat despre adăugarea și eliminarea ascultătorilor de evenimente, este timpul să aflăm
despre etapele unui eveniment!
Recapitulare

În această secțiune, ați aflat despre cum să eliminați ascultătorii de evenimente. Ați făcut o analiză
despre egalitatea obiectelor și modul în care acest lucru joacă un rol imens în eliminarea unui
eveniment. În cele din urmă, ne-am uitat și la modul în care puteți afla ce ascultător de evenimente
are un element DOM utilizând DevTools.

Cercetări suplimentare

 removeEventListener pe MDN
 Salt cu ușurință la ascultătorii de evenimente
 Comparații și egalitate de egalitate
 Articol: Egalitatea obiectelor în JavaScript
 Interfață EventTarget

Faze de eveniment
Există trei faze diferite pe parcursul ciclului de viață al unui eveniment. Sunt:

1. Faza de capturing
2. Faza de target
3. Faza de bubbling

Și ei respectă de fapt ordinea de mai sus; mai întâi, captează , apoi la țintă și apoi faza de bubbling.

Majoritatea gestionarelor de evenimente rulează în timpul fazei țintă , cum ar fi atunci când atașați
un buton de gestionare a evenimentelor cu clic. Evenimentul ajunge la buton ( ținta sa ) și există
doar un handler pentru el chiar acolo, astfel încât handlerul evenimentului să fie rulat.

Dar, uneori, aveți o colecție de articole - cum ar fi o listă - și doriți să aveți un singur handler care să
acopere fiecare articol (și totuși aveți opțiunea de handlers individuali pentru unele articole.) În mod
implicit, dacă faceți clic pe un element secundar și un handler nu interceptează clicul, evenimentul
va merge în sus către părinte și va continua să clocotească până când ceva îl rezolvă sau atinge
documentul.

Captarea, pe de altă parte, permite părintelui să intercepteze un eveniment înainte ca acesta să


ajungă la un copil.

Să vedem cum aceste faze afectează atunci când evenimentele se declanșează și ordinea în care
merg!

Explicația: https://www.youtube.com/watch?v=rGhgPPYc2sg&feature=emb_logo
Deci, din cele trei faze ale unui eveniment, pe care o folosește de fapt metoda .addEventListener()?
Și, cum o putem schimba?

Până în acest moment, am văzut metoda .addEventListener() numită doar cu două argumente:

- tipul evenimentului
- și ascultătorul

Există de fapt un al treilea argument al metodei .addEventListener(): argumentul useCapture. Din


numele său, ați crede că, dacă acest argument ar fi lăsat în afara, .addEventListener() ar folosi în mod
implicit faza de capturare . Aceasta este o presupunere incorectă! În mod implicit, atunci când
.addEventListener() este apelat cu doar două argumente, metoda implicită folosește faza de
bubbling.

Codul de mai jos folosește doar două argumente .addEventListener(), așa că va invoca ascultătorul în
timpul fazei de bubbling:

Cu toate acestea, în acest cod, .addEventListener() este apelat cu trei argumente, al treilea argument
fiind true (adică ar trebui să invoce ascultătorul mai devreme, în timpul fazei de captare !).
Pentru mai multe detalii, accesați: https://www.youtube.com/watch?
v=4WYyk3AhCOU&feature=emb_logo

Obiectul evenimentului

Acum, că știți că ascultătorii de evenimente se declanșează într-o ordine specifică și cum să


interpretați și să controlați acea ordine, este timpul să vă deplasați la detaliile evenimentului în sine.

Când apare un eveniment, browserul include un obiect de eveniment . Acesta este doar un obiect
JavaScript obișnuit care include o mulțime de informații despre evenimentul în sine. Potrivit MDN,
funcția .addEventListener() primește: o notificare (un obiect care implementează interfața
evenimentului) atunci când are loc un eveniment de tipul specificat.

Până în acest moment, am scris toate funcțiile ascultătorului fără niciun parametru pentru a stoca
acest obiect eveniment. Să adăugăm un parametru pentru a putea stoca aceste informații
importante:

Observați noul parametru event care a fost adăugat funcției ascultător. Acum, când funcția de
ascultător este apelată, este capabilă să stocheze datele despre eveniment care i-au fost transmise!

💡 Un „eveniment” poate fi numit „evt” sau „e” 💡

Amintiți-vă că parametrul unei funcții este la fel ca o variabilă obișnuită. În exemplul următor,
folosesc un parametru cu numele event.
Event, numele parametrului ar putea fi la fel de ușor numit și:

- evt
- e
- theEvent
- horse

Numele event sau evt nu oferă nici un sens inerent sau capacități speciale; nu este nimic special
pentru nume ... este doar numele parametrului. Simțiți-vă liber să îi dați orice nume informativ /
descriptiv!

Mai multe detalii: https://www.youtube.com/watch?v=134IQEN89VQ&feature=emb_logo

Acțiunea implicită

După cum tocmai ne-am uitat, obiectul eveniment stochează o mulțime de informații și putem folosi
aceste date pentru a face tot felul de lucruri. Cu toate acestea, un motiv incredibil de obișnuit pentru
care profesioniștii folosesc obiectul eveniment este acela de a preveni acțiunea implicită. Sună ca un
lucru ciudat de făcut, dar hai să explorăm acest lucru.

Gândiți-vă la un link de ancorare pe o pagină web. Există probabil câteva zeci de linkuri pe această
pagină! Ce se întâmplă dacă doriți să rulați un anumit cod și să afișați o ieșire când faceți clic pe una
dintre aceste legături. Dacă faceți clic pe link, acesta va naviga automat la locația listată în atributul
său href: asta face în mod implicit.

Dar un element de formular? Când trimiteți un formular, în mod implicit, acesta va trimite datele
către locația din atributul său action. Dar dacă am dori să validăm datele înainte de a le trimite,
totuși?

Fără obiectul evenimentului, suntem blocați cu acțiunile implicite. Cu toate acestea, obiectul
eveniment are o metodă .preventDefault()pe care un handler o poate apela pentru a împiedica să se
întâmple acțiunea implicită!
Recapitulare

Am acoperit o serie de aspecte importante ale evenimentelor și ascultătorilor de evenimente în


această secțiune! Ne-am uitat la:

- fazele unui eveniment:


 capturing faza
 at target faza
 bubbling faza
- obiectul evenimentului
- preveniți acțiunea implicită cu .preventDefault()

Cercetări suplimentare

 Expedierea evenimentului și fluxul de evenimente DOM pe W3C


 faza de captare pe W3C
 faza țintă pe W3C
 faza cu bule pe W3C
 Eveniment pe MDN
 Referința evenimentului pe MDN
 addEventListener pe MDN

DOM-ul este construit incremental

Atunci când codul HTML este primit și convertit în jetoane și încorporat în modelul de obiect
document, este că acesta este un proces secvențial. Când analizorul ajunge la o etichetă <script>,
trebuie să aștepte să descarce fișierul script și să execute acel cod JavaScript. Aceasta este partea
importantă și cheia pentru care contează plasarea fișierului JavaScript!

Să ne uităm la un cod pentru a arăta (mai mult sau mai puțin) ce se întâmplă. Aruncați o privire la
această parte inițială a unui fișier HTML:

<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="/css/styles.css" />
<script>
document.querySelector('footer').style.backgroundColor = 'purple';
</script>

Acesta nu este fișierul HTML complet ... DAR, este tot ce a fost analizat până acum. Observați în
partea de jos a codului că avem până acum un <script>fișier. Aceasta utilizează JavaScript în linie,
mai degrabă decât să arate spre un fișier extern. Fișierul în linie se va executa mai repede, deoarece
browserul nu trebuie să facă o altă cerere de rețea pentru a prelua fișierul JavaScript. Dar rezultatul
va fi exact același atât pentru această versiune inline, cât și dacă HTML s-ar fi legat de un fișier
JavaScript extern.

Vedeți codul JavaScript/DOM în etichete <script>?

document.querySelector('footer').style.backgroundColor = 'purple';
Acest cod este complet lipsit de erori ... din păcate, atunci când rulează, va provoca în continuare o
eroare. Aveți idei de ce?

Problema este cu metoda .querySelector()metoda. Când rulează ... nu există încă niciun element
<footer> de selectat din modelul de obiect de document construit! Deci, în loc să returneze un
element DOM, acesta va reveni null. Acest lucru provoacă o eroare deoarece ar fi ca și cum ați rula
următorul cod:

null.style.backgroundColor = 'purple';

Null nu are o proprietate .style, deci astfel apare eroarea noastră.

Acum, am folosit deja o soluție la această problemă. Amintiți-vă că am mutat fișierul JavaScript în
josul paginii. Gândiți-vă de ce acest lucru ar face lucrurile să funcționeze. Ei bine, dacă DOM-ul este
construit secvențial, dacă codul JavaScript este mutat chiar în partea de jos a paginii, atunci până
când rulează codul JavaScript, toate elementele DOM vor exista deja!

Cu toate acestea, o soluție alternativă ar fi utilizarea evenimentelor din browser! 🙌🏼

Conținutul este încărcat Eveniment

Când modelul obiectului documentului a fost încărcat complet, browserul va declanșa un eveniment.
Acest eveniment se numește DOMContentLoaded eveniment și îl putem asculta în același mod în
care ascultăm orice alte evenimente:

document.addEventListener('DOMContentLoaded', function () {
console.log('the DOM is ready to be interacted with!');
});

Vedeți: https://www.youtube.com/watch?v=bmtMp4Rgryc&feature=emb_logo
Folosind evenimentul DOMContentLoaded

Deoarece acum știm despre evenimentul DOMContentLoaded, îl putem folosi pentru a păstra codul
nostru JS în <head>.

Să actualizăm codul HTML anterior pentru a include acest eveniment:

<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="/css/styles.css" />
<script>
document.addEventListener('DOMContentLoaded', function () {
document.querySelector('footer').style.backgroundColor = 'purple';
});
</script>
Destul de cool, nu?!? Avem codul JavaScript în element ul <head>, dar acum este înfășurat într-un
ascultător de evenimente pentru evenimentul DOMContentLoaded. Acest lucru va împiedica rularea
codului de stilare DOM atunci când browserul ajunge la acesta. Apoi, când DOM-ul a fost construit,
evenimentul se va declanșa și acest cod va rula.

Dacă vă uitați la codul altcuiva, este posibil să vedeți că codul lor ascultă load evenimentul utilizat în
loc (de exemplu document.onload(...)). Load se declanșează mai târziu de DOMContentLoaded- load
așteaptă până când toate imaginile, foile de stil etc. au fost încărcate (totul la care face referire
HTML). Mulți dezvoltatori mai vechi îl folosesc load în loc DOMContentLoaded ca acesta din urmă să
nu fie suportat de cele mai vechi browsere. Dar dacă trebuie să detectați când codul dvs. poate rula,
DOMContentLoaded este în general cea mai bună alegere.

Cu toate acestea, doar pentru că puteți utiliza DOMContentLoaded evenimentul pentru a scrie cod
JavaScript în <head> acest lucru nu înseamnă că ar trebui să faceți acest lucru. Procedând astfel,
trebuie să scriem mai multe coduri (toate lucrurile care ascultă evenimentele), iar mai mult cod nu
este întotdeauna cel mai bun mod de a face ceva. În schimb, ar fi mai bine să mutați codul în partea
de jos a fișierului HTML chiar înainte de </body>eticheta de închidere .

Deci, când ai vrea să folosești această tehnică? Ei bine, codul JavaScript <head>va rula înainte de
codul JavaScript <body>, așadar, dacă aveți un cod JavaScript care trebuie să ruleze cât mai curând
posibil , atunci puteți pune acel cod în <head>și îl puteți înfășura într-un DOMContentLoaded
ascultător de evenimente. În acest fel, va rula cât mai devreme posibil, dar nu prea devreme pentru
ca DOM să nu fie pregătit pentru asta.

Recapitulare

În această secțiune, am aflat despre DOMContentLoaded evenimentul util.

Pe parcurs, am analizat modul în care codul HTML este analizat incremental și modul în care acesta
afectează codul JavaScript / DOM. De asemenea, ne-am uitat la motivul pentru care scrierea codului
de manipulare DOM în acest document <head>poate provoca erori.

Cercetări suplimentare

 DOMContentLoaded Documente de evenimente pe MDN

S-ar putea să vă placă și