Cheia ascunsă pentru interacțiunile web dinamice

Când încă învățam frânghiile dezvoltării web, unul dintre comportamentele surprinzătoare și intrigante pe care le-am întâlnit a fost bulionul de evenimente. La început, părea neobișnuit, dar când te gândești la barbotarea evenimentelor, vei vedea că are atât de mult sens. În calitate de dezvoltator web, este neapărat să întâmpinați bule de evenimente. Așadar, ce este balonarea evenimentului?

Pentru a oferi utilizatorilor posibilitatea de a interacționa cu paginile web, JavaScript se bazează pe evenimente. Un eveniment se referă la apariții sau acțiuni care pot fi detectate și la care se poate răspunde prin codul pe care îl scrieți. Exemple de evenimente includ clicuri de mouse, apăsări de taste și trimitere de formulare, printre altele.

JavaScript folosește ascultători de evenimente pentru a detecta și a răspunde la evenimente. Un ascultător de evenimente este o funcție care ascultă sau așteaptă ca un anumit eveniment să apară pe o pagină. De exemplu, un eveniment de clic pe un buton. Când un ascultător de evenimente detectează evenimentul pe care îl ascultă, acesta răspunde executând codul asociat evenimentului. Acest întreg proces de captare și răspuns la evenimente se numește gestionarea evenimentelor.

Acum, imaginați-vă că avem trei elemente pe o pagină: un div, un interval și un buton. Elementul buton este imbricat în interiorul elementului span, iar elementul span este imbricat în interiorul div. O ilustrare a acestui lucru este prezentată mai jos:

Presupunând că fiecare dintre aceste elemente are un ascultător de evenimente care ascultă un eveniment de clic și se imprimă pe consolă atunci când se face clic, ce se întâmplă când faceți clic pe buton?

Pentru a testa acest lucru singur, creați un folder, iar în folder, creați un fișier HTML numit index.html, un fișier CSS numit style.css și un fișier JavaScript numit app.js.

În fișierul HTML, adăugați următorul cod:

<!DOCTYPE html>
<html lang="en">

<head>
  <title>Event bubbling</title>
  <link rel="stylesheet" href="https://wilku.top/the-hidden-key-to-dynamic-web-interactions/style.css">
</head>

<body>
  <div>
    <span><button>Click Me!</button></span>
  </div>
  <script src="app.js"></script>
</body>

</html>

În fișierul CSS, adăugați următorul cod pentru a stila elementul div și span.

div {
  border: 2px solid black;
  background-color: orange;
  padding: 30px;
  width: 400px;
}

span {
  display: inline-block;
  background-color: cyan;
  height: 100px;
  width: 200px;
  margin: 10px;
  padding: 20px;
  border: 2px solid black;
}

În fișierul JavaScript, adăugați următorul cod, care adaugă ascultători de evenimente la elementele div, span și buton. Toate listele de evenimente ascultă un eveniment clic.

const div = document.querySelector('div');
div.addEventListener('click', () => {
  console.log("You've clicked a div element")
})

const span = document.querySelector('span');
span.addEventListener('click', () => {
  console.log("You've clicked a span element")
})

const button = document.querySelector('button');
button.addEventListener('click', () => {
  console.log("You've clicked a button")
})

Acum deschideți fișierul HTML într-un browser. Inspectați pagina, apoi faceți clic pe butonul de pe pagină. Ce observi? Rezultatul clicului pe buton este afișat mai jos:

Făcând clic pe butonul declanșează ascultătorul evenimentului care ascultă un eveniment clic pe buton. Cu toate acestea, ascultătorii de evenimente de pe elementele span și div sunt, de asemenea, declanșați. De ce este acesta cazul, te-ai putea întreba.

Făcând clic pe butonul declanșează ascultătorul de evenimente atașat butonului, care se imprimă pe consolă. Cu toate acestea, deoarece butonul este imbricat în interiorul unui element span, a face clic pe buton înseamnă că, din punct de vedere tehnic, facem clic și pe elementul span și, prin urmare, ascultătorul său de evenimente este declanșat.

  Cele mai bune plăci de bază B760 din 2024

Deoarece elementul span este, de asemenea, imbricat în interiorul elementului div, a face clic pe elementul span înseamnă, de asemenea, că se face clic și pe elementul div și, ca urmare, ascultătorul său de evenimente este de asemenea declanșat. Acesta este un eveniment fulgerător.

Barbotare de evenimente

Barbotarea evenimentelor este procesul prin care un eveniment declanșat într-un set imbricat de elemente HTML este propagat sau se ridică din elementul cel mai interior unde a fost declanșat și se deplasează în arborele DOM până la elementul rădăcină, declanșând toți ascultătorii de evenimente care ascultă evenimentul respectiv.

Ascultătorii de evenimente sunt declanșați într-o anumită ordine care se potrivește cu modul în care evenimentul se răspândește sau se propagă în arborele DOM. Luați în considerare arborele DOM prezentat mai jos, care reprezintă structura HTML-ului folosit în acest articol.

Un eveniment de clic care se ridică în arborele DOM

Arborele DOM arată un buton, imbricat într-un interval, care este imbricat în interiorul unui div, care este imbricat în interiorul corpului, iar corpul este imbricat în interiorul elementului HTML. Deoarece elementele au fost imbricate unul în celălalt atunci când faceți clic pe buton, evenimentul de clic va declanșa ascultătorul de evenimente atașat butonului.

Cu toate acestea, deoarece elementele sunt imbricate, evenimentul se va deplasa în sus în arborele DOM (bule în sus) la elementul span, apoi div-ul, apoi corpul și, în final, elementul HTML, declanșând toți ascultătorii de evenimente care ascultă un eveniment clic în acel moment. Ordin.

Acesta este motivul pentru care ascultătorul de evenimente atașat elementelor span și div este executat. Dacă am fi avut ascultători de evenimente care ascultă un clic pe corp și pe elementul HTML, ar fi fost declanșați și ei.

Nodul DOM unde are loc un eveniment se numește țintă. În cazul nostru, deoarece clicul are loc pe buton, elementul butonului este ținta evenimentului.

Cum să opriți barbotarea evenimentelor

Pentru a opri un eveniment de la barbotarea DOM, folosim o metodă numită stopPropagation() care este disponibilă pe obiectul eveniment. Luați în considerare exemplul de cod de mai jos, pe care l-am folosit pentru a adăuga un ascultător de evenimente la elementul buton.

const button = document.querySelector('button');
button.addEventListener('click', () => {
  console.log("You've clicked a button");
})

Codul duce la un eveniment care se ridică în arborele DOM atunci când un utilizator dă clic pe buton. Pentru a preveni barbotarea evenimentelor, apelăm metoda stopPropagation() după cum se arată mai jos:

const button = document.querySelector('button');
button.addEventListener('click', (e) => {
  console.log("You've clicked a button");
  e.stopPropagation();
})

Un handler de evenimente este funcția care este executată atunci când se face clic pe un buton. Un ascultător de evenimente transmite automat un obiect eveniment unui handler de evenimente. În cazul nostru, acest obiect eveniment este reprezentat de numele variabilei e, care este transmis ca parametru în handlerul de evenimente.

Acest obiect eveniment, e, conține informații despre un eveniment și, de asemenea, ne oferă acces la o varietate de proprietăți și metode legate de evenimente. O astfel de metodă este stopPropagation(), care este folosită pentru a preveni bulele evenimentelor. Apelarea stopPropagation() în ascultătorul de evenimente al butonului împiedică un eveniment să apară în arborele DOM din elementul buton.

  15 biblioteci de tabele JavaScript de utilizat pentru prezentarea ușoară a datelor tipstrick.ro

Rezultatul clicului pe butonul după adăugarea metodei stopPropagation() este afișat mai jos:

Folosim stopPropagation() pentru a preveni apariția unui eveniment din elementul pe care îl folosim. De exemplu, dacă dorim ca evenimentul click să urce de la elementul buton până la elementul span și să nu bule mai sus în arborele DOM, am folosi stopPropagation() pe ascultătorul de evenimente al span.

Capturarea evenimentelor

Capturarea evenimentelor este opusul bubuirii evenimentelor. În capturarea evenimentelor, un eveniment se scurge de la elementul cel mai exterior la elementul țintă, așa cum este ilustrat mai jos:

Faceți clic pe eveniment care se scurge în jos la elementul țintă din cauza capturii evenimentului

De exemplu, în cazul nostru, când faceți clic pe elementul buton, în capturarea evenimentului, ascultătorii de evenimente de pe elementul div vor fi primii declanșați. Urmează ascultătorii de pe elementul span și, în final, vor fi declanșați ascultătorii de pe elementul țintă.

Event bubble-ul este, totuși, modul implicit în care evenimentele sunt propagate în Document Object Model (DOM). Pentru a schimba comportamentul implicit de la bule de evenimente la capturarea evenimentelor, transmitem un al treilea argument ascultătorilor noștri de evenimente pentru a seta capturarea evenimentelor la adevărat. Dacă nu transmiteți un al treilea argument ascultătorilor de evenimente, capturarea evenimentului este setată la fals.

Luați în considerare ascultătorul evenimentului de mai jos:

div.addEventListener('click', () => {
  console.log("You've clicked a div element")
})

Deoarece nu are un al treilea argument, capturarea este setată la fals. Pentru a seta capturarea la adevărat, trecem un al treilea argument, valoarea booleană true, care setează capturarea la adevărat.

div.addEventListener('click', () => {
  console.log("You've clicked a div element")
}, true)

Alternativ, puteți trece un obiect care setează captura la adevărat, după cum se arată mai jos:

div.addEventListener('click', () => {
  console.log("You've clicked a div element")
}, {capture: true})

Pentru a testa capturarea evenimentelor, în fișierul JavaScript, adăugați un al treilea argument la toți ascultătorii de evenimente, așa cum se arată:

const div = document.querySelector('div');
div.addEventListener('click', () => {
  console.log("You've clicked a div element")
}, true)

const span = document.querySelector('span');
span.addEventListener('click', (e) => {
  console.log("You've clicked a span element")
}, true)

const button = document.querySelector('button');
button.addEventListener('click', () => {
  console.log("You've clicked a button");
}, true)

Acum deschideți browserul și faceți clic pe elementul butonului. Ar trebui să obțineți o astfel de ieșire:

Observați că, spre deosebire de barbotarea evenimentelor, unde ieșirea de la buton a fost tipărită prima, în capturarea de evenimente, prima ieșire este de la elementul cel mai exterior, div.

Bubble-ul de evenimente și capturarea evenimentelor sunt principalele modalități prin care evenimentele sunt propagate în DOM. Cu toate acestea, barbotarea evenimentelor este ceea ce este folosit în mod obișnuit pentru a propaga evenimente.

Delegarea evenimentului

Delegarea evenimentului este un model de proiectare în care un singur ascultător de eveniment este atașat la un element părinte comun, de exemplu un element

    , în loc să aibă ascultători de evenimente pe fiecare dintre elementele copil. Evenimentele de pe elementele copil apar apoi la elementul părinte, unde sunt gestionate de handlerul de evenimente de pe elementul părinte.

    Prin urmare, într-un caz în care avem un element părinte cu elemente copil în el, adăugăm doar un ascultător de evenimente la elementul părinte. Acest handler de evenimente se va ocupa de toate evenimentele din elementele copil.

    S-ar putea să vă întrebați cum va ști elementul părinte pe ce element copil a fost făcut clic. După cum sa menționat anterior, un ascultător de evenimente transmite un obiect eveniment unui handler de evenimente. Acest obiect eveniment are metode și proprietăți care oferă informații despre un anumit eveniment. Una dintre proprietățile obiectului eveniment este proprietatea țintă. Proprietatea țintă indică elementul HTML specific în care a avut loc un eveniment.

    De exemplu, dacă avem o listă neordonată cu elemente de listă și atașăm un ascultător de evenimente la elementul

      atunci când are loc un eveniment pe un element de listă, proprietatea țintă din obiectul eveniment va indica elementul specific din listă unde evenimentul a avut loc.

      Pentru a vedea delegarea evenimentului în acțiune, adăugați următorul cod HTML la fișierul HTML existent:

      <ul>
          <li>Toyota</li>
          <li>Subaru</li>
          <li>Honda</li>
          <li>Hyundai</li>
          <li>Chevrolet</li>
          <li>Kia</li>
        </ul>

      Adăugați următorul cod JavaScript pentru a utiliza delegarea evenimentelor pentru a utiliza un singur ascultător de evenimente pe un element părinte pentru a asculta evenimente în elementele copil:

      const ul = document.querySelector('ul');
      ul.addEventListener('click', (e) => {
        // target element
        targetElement = e.target
        // log out the content of the target element
        console.log(targetElement.textContent)
      })

      Acum deschideți browserul și faceți clic pe orice element din listă. Conținutul elementului ar trebui să fie imprimat pe consolă, așa cum se arată mai jos:

      Folosind un singur ascultător de evenimente, putem gestiona evenimente în toate elementele copil. Având atât de mulți ascultători de evenimente pe o pagină, îi afectează performanța, consumă mai multă memorie și duce la încărcarea și redarea lentă a paginilor.

      Delegarea evenimentelor ne permite să evităm toate acestea, reducând la minimum numărul de ascultători de evenimente pe care trebuie să-i folosim pe o pagină. Delegarea evenimentului se bazează pe balonarea evenimentului. Prin urmare, putem spune că balonarea evenimentelor poate ajuta la optimizarea performanței paginilor web.

      Sfaturi pentru gestionarea eficientă a evenimentelor

      În calitate de dezvoltator, atunci când lucrați cu evenimente în modelul obiect document, luați în considerare utilizarea delegării evenimentelor, mai degrabă decât a avea o mulțime de ascultători de evenimente pe elementele din pagina dvs.

      Când utilizați delegarea evenimentelor, amintiți-vă să atașați un ascultător de evenimente celui mai apropiat strămoș comun al elementelor copil care necesită gestionarea evenimentelor. Acest lucru ajută la optimizarea fenomenului de barbotare și, de asemenea, minimizează calea pe care trebuie să o parcurgă un eveniment înainte de a fi gestionat.

      Când gestionați evenimente, utilizați obiectul eveniment care este furnizat de ascultătorul de evenimente în avantajul dvs. Obiectul eveniment conține proprietăți precum ținta, care sunt utile în gestionarea evenimentelor.

      Pentru a avea site-uri web mai performante, evitați manipularea excesivă a DOM. Apariția unor evenimente care declanșează manipulări frecvente DOM poate afecta negativ performanța site-ului dvs.

      În cele din urmă, în cazul elementelor imbricate, fiți foarte precauți atunci când atașați ascultători de evenimente imbricate la elemente. Acest lucru nu poate afecta doar performanța, dar va face gestionarea evenimentelor foarte complexă, iar codul dvs. va fi greu de întreținut.

      Concluzie

      Evenimentele sunt un instrument puternic în JavaScript. Barbotarea evenimentelor, capturarea evenimentelor și delegarea evenimentelor sunt instrumente importante în gestionarea evenimentelor în JavaScript. În calitate de dezvoltator web, utilizați articolul pentru a vă familiariza cu conceptele, astfel încât să puteți construi site-uri web și aplicații mai interactive, dinamice și performante.