Js događaj mjehurić. JavaScript - Bubbling događaja. Kako većina njih radi?

💖 Sviđa li vam se? Podijelite vezu sa svojim prijateljima

Sada ćemo pogledati neke napredne stvari pri radu s objektom Event, naime: bubbling i presretanje, kao i delegiranje događaja.

Pjenušavi događaji

Zamislite da imate nekoliko blokova ugniježđenih jedan u drugi:

najunutarnji blok

Kada kliknete na najunutarnji blok, događaj onclick aktivira se prvo na njemu, a zatim se aktivira na njegovom roditelju, na roditeljskom roditelju i tako dalje dok ne dođe do oznake tijela, a zatim do html oznaka(zatim na dokument i na prozor).

I to je logično, jer kada kliknete na unutarnji blok, istovremeno kliknete na sve vanjske.

Pogledajmo to na sljedećem primjeru: imamo 3 bloka, svaki od njih ima priložen događaj onclick:

Kliknite na najunutarnji crveni blok - i vidjet ćete kako radi klik prvo na crveni blok, zatim na plavi, pa na zeleni:

Ovo ponašanje se zove naranjanjem događaja - po analogiji s izlaskom mjehurića zraka s dna. Baš poput mjehurića, naš klik na unutarnji element kao da lebdi na vrhu, svaki put se aktivirajući na višim blokovima.

događaj.cilja

Neka nam budu dva elementa: div i odlomak p koji se nalazi unutar ovog diva. Vežimo onlick za div:

Kada kliknemo na ovaj div, možemo otići na odlomak ili možemo otići na mjesto gdje ovaj odlomak ne postoji.

Kako to može biti - pogledajte sljedeći primjer: zelene boje je naš div, a plavi je naš paragraf:

Ako kliknemo na zeleni dio, kliknut ćemo na div, a ako kliknemo na plavi dio, klik će se prvo dogoditi na paragraf, a zatim na div. No budući da je onclick posebno pridružen divu, općenito možda nećemo primijetiti prisutnost odlomka.

Međutim, ponekad želimo znati je li se klik dogodio izravno na div ili na njegov odlomak potomak. U tome će nam pomoći objekt Event i njegovo svojstvo event.target - ono pohranjuje točno onaj element u kojem se klik dogodio.

U sljedećem primjeru imamo div s p unutar njega i span unutar njega.

Idemo sami vezati onclick događaj gornji element(div) i klikat ćemo na različite elemente: div, p, span. Korištenjem event.target dobit ćemo najniži element u kojem se događaj dogodio i prikazati njegovo ime koristeći tagName.

Ako kliknete, na primjer, na span, tada će događaj uhvatiti naš div (uostalom, onclick mu je pridodat), ali će span biti u event.target:

Kliknite na različite blokove - vidjet ćete rezultat:

Zaustavljanje uspona

Dakle, već znate da se svi događaji penju na sam vrh (na html tag, pa na dokument, pa na prozor). Ponekad je potrebno zaustaviti ovaj uspon. Svaki element preko kojeg mjehurići događaja mogu to učiniti. Da biste to učinili, pozovite metodu event.stopPropagation() u kodu elementa.

U sljedećem primjeru, klik na crveni blok će raditi na sebi, zatim na plavi blok i to je to - plavi blok prestaje dalje iskakati, a zeleni blok neće reagirati ni na koji način:

Kliknite na crveni blok - vidjet ćete rezultat:

Ronjenje

Osim nastanka događaja postoji i ronjenje(prema fazi znanstvenog presretanja). To znači da događaj prvo dolazi odozgo prema dolje (faza presretanja), dolazi do našeg elementa (faza cilja) i tek onda počinje izlaziti (faza uspona).

Rukovatelja događajem možete priložiti samo uzimajući u obzir fazu presretanja koristeći addEventListener. Za to ima treći parametar: ako je istinit, događaj će se pokrenuti u fazi presretanja, a ako je lažan, u fazi mjehurića (ovo je zadano):

Var green = document.getElementById("green"); green.addEventListener("klik", func, istina); funkcija func(event) ( )

Faza u kojoj se događaj dogodio može se odrediti pomoću svojstva event.eventPhase. Može imati sljedeće vrijednosti: 1 - stupanj presretanja, 2 - stupanj cilja, 3 - stupanj izrona.

Uvod u delegaciju

Zamislimo situaciju: neka nam je ul s nekoliko li . Sljedeći događaj je priložen svakom liju: kada kliknete na li, na njegov kraj se dodaje “!”.

Provedimo opisano:

  • stavak 1
  • točka 2
  • točka 3
  • točka 4
  • točka 5
var li = document.querySelectorAll("#ul li"); //U petlji pridružujemo funkciju addSign svakom li: for (var i = 0; i

Kliknite na li - vidjet ćete kako se “!” dodaje na kraj:

  • stavak 1
  • točka 2
  • točka 3
  • točka 4
  • točka 5

Sada imamo i gumb, kada se klikne, dodaje se novi li s tekstom “stavka” na kraj ul. Čeka nas iznenađenje: vezani događaj neće raditi za nove likove! Uvjerimo se u ovo:

  • stavak 1
  • točka 2
  • točka 3
  • točka 4
  • točka 5
Dodajte li

Kliknite na gumb za dodavanje li, a zatim na ovaj novi li - neće reagirati:

  • stavak 1
  • točka 2
  • točka 3
  • točka 4
  • točka 5
Dodajte li

Da biste riješili problem, kada stvarate novi li, možete mu dodati funkciju addSign putem addEventListener. Implementirajmo ovo:

  • stavak 1
  • točka 2
  • točka 3
  • točka 4
  • točka 5
Dodaj li var li = document.querySelectorAll("#ul li"); za (var i = 0; i

  • stavak 1
  • točka 2
  • točka 3
  • točka 4
  • točka 5
Dodajte li

Postoji drugi način da se zaobiđe problem - delegiranje događaja. Razbijmo to.

Delegiranje događaja

Suština delegiranja je sljedeća: dodijelimo događaj ne svakom li, već njihovom roditelju - na ul.

U isto vrijeme, funkcionalnost naše skripte bi trebala ostati: kao i prije, kada kliknete na li, "!" će se dodati na njen kraj. Samo će događaj u novoj verziji biti priložen na ul:

Var ul = document.getElementById("ul"); //Priložite događaj na ul: ul.addEventListener("click", addSign); funkcija addSign() ( )

Kako ćemo to provjeriti: budući da je događaj pridružen ul, tada unutar funkcije možemo uhvatiti li pomoću event.target. Da vas podsjetim što je event.target - to je upravo tag u kojem se dogodio klik, u našem slučaju to je li .

Dakle, evo rješenja našeg problema kroz delegiranje:

  • stavak 1
  • točka 2
  • točka 3
  • točka 4
  • točka 5

Rezultat izvršavanja koda:

  • stavak 1
  • točka 2
  • točka 3
  • točka 4
  • točka 5

Štoviše, naše rješenje će raditi automatski čak i za novi li, jer događaj nije dodijeljen li, već ul:

  • stavak 1
  • točka 2
  • točka 3
  • točka 4
  • točka 5
Dodajte li var ul = document.getElementById("ul"); ul.addEventListener("klik", addSign); function addSign() ( event.target.innerHTML = event.target.innerHTML + "!"; ) //Implementacija gumba za dodavanje novog li: var button = document.getElementById("button"); button.addEventListener("klik", addLi); funkcija addLi() ( var li = document.createElement("li"); li.innerHTML = "novi li"; ul.appendChild(li); )

Kliknite na gumb za dodavanje li, a zatim na ovaj novi li - reagirat će:

  • stavak 1
  • točka 2
  • točka 3
  • točka 4
  • točka 5
Dodajte li

Naš kôd radi, ali ne bez nedostataka. Pogledajmo ove nedostatke i napišimo univerzalnije rješenje.

Delegiranje univerzalnog događaja

Nedostatak našeg koda će se očitovati kada postoje neke ugniježđene oznake unutar li. U našem slučaju, neka ovo budu i oznake:

U ovom slučaju, pritiskom na i će se dodati uskličnik do kraja oznake i, a ne oznake li, kako bismo htjeli (ako kliknete na li izvan kurziva, onda će sve biti u redu):

  • paragraf kurziv 1
  • paragraf kurziv 2
  • paragraf kurziv 3
  • paragraf kurziv 4
  • paragraf kurziv 5
var ul = document.getElementById("ul"); ul.addEventListener("klik", addSign); funkcija addSign() ( event.target.innerHTML = event.target.innerHTML + "!"; )

Kliknite na kurziv - vidjet ćete kako "!" bit će dodan na kraj toga (pritiskom na vanjski kurziv dobro će funkcionirati):

Problem se rješava na sljedeći način (opisana metoda nije jedina, već je najjednostavnija): korištenjem najbliže metode pronalazimo najbliži li, koji je roditelj event.target ovako: event.target.closest(" li") .

Kako radi: ako je klik bio na i, tada event.target sadrži ovo i, a event.target.closest("li") sadrži naš li za koji bi se događaj trebao pokrenuti.

Ako je klik bio na sam li, tada će i event.target i event.target.closest("li") sadržavati naš li.

Provjerimo:

  • paragraf kurziv 1
  • paragraf kurziv 2
  • paragraf kurziv 3
  • paragraf kurziv 4
  • paragraf kurziv 5
var ul = document.getElementById("ul"); ul.addEventListener("click", function(event) ( var li = event.target.closest("li"); if (li) ( //provjeri postoji li uopće roditelj li.innerHTML = li.innerHTML + "!";) ));

Rezultat izvršavanja koda:

Nije bitno koja je dubina ugniježđenja: i tag može ležati u b tag-u, i to u span tagu pa tek onda u li - nije bitno: event.target.closest("li" ) konstrukcija će pronaći roditelja s bilo koje razine gniježđenja.

U ovoj lekciji ćemo se upoznati s konceptom bubblinga događaja, a također ćemo pogledati kako se ono može prekinuti. Osim toga, saznat ćemo kroz koje još faze (faze) događaj prolazi prije nego što se počne pojavljivati.

Oblačić događaja

Ako se dogodi događaj za neki element, on počinje “iskakati”, tj. javlja se kod roditelja, zatim kod bake i djeda itd.

Iz toga slijedi da se događaj generiran nekim elementom može presresti korištenjem rukovatelja na roditelju, baki i djedu itd.

Demonstrirat ćemo nastanak događaja (mjehurića) koristeći sljedeći primjer:

Naslov

Neki vrlo važan tekst

Poglavlje

Neki tekst

Ostatak teksta

Napišimo malu skriptu kojom ćemo dodati rukovatelj događajima "klik" za sve elemente stranice, kao i za objekte dokumenta i prozora.

document.addEventListener("DOMContentLoaded", function() ( var allElements = document.getElementsByTagName("*"); for (var i=0; i< allElements.length; i++) { allElements[i].addEventListener("click",function() {console.log(this.tagName);},false); }; document.addEventListener("click",function() {console.log(this);},false); window.addEventListener("click",function() {console.log(this);},false); });

Kreirajmo HTML stranicu i zalijepimo gornji HTML kod u nju. Umetnut ćemo skriptu napisanu u JavaScriptu prije završne oznake tijela. Nakon toga otvorite novostvorenu stranicu u web pregledniku, pritisnite tipku F12 i idite na konzolu. Kliknimo sada lijevom tipkom miša na područje koje pripada jakom elementu i pogledajmo kako se događaj pojavljuje.

Kako prekinuti bubbling događaja

Dizanje događaja (mjehurića) može se prekinuti. U tom slučaju, ovaj se događaj neće pokrenuti za više (roditeljske) elemente. Metoda koja je dizajnirana za zaustavljanje širenja događaja (mjehurića) zove se stopPropagation().

Na primjer, promijenimo naš gornji primjer tako da se događaj ne pojavljuje iznad tijela: document.addEventListener("DOMContentLoaded", function() ( var allElements = document.getElementsByTagName("*"); for (var i=0 ; i

Bez sumnje, oblaganje je vrlo zgodno i arhitektonski transparentno. Nemojte ga zaustavljati osim ako nije apsolutno neophodno.

Dohvaćanje elementa koji je pozvao rukovatelja

Da biste dobili DOM element (objekt) koji je pozvao rukovatelj događajima, morate koristiti ključna riječ ovaj. Ova ključna riječ (ovo) dostupna je samo u rukovatelju ako se pretplatite na događaj koristeći JavaScript.

Na primjer, prikažimo u konzoli ID elementa koji je pozvao rukovatelja događajima:

Var myP = document.getElementById("myP"); myP.addEventListener("click",function())( //dobijte DOM element koji je pozvao rukovatelj događajima - ovo //dobijte njegov ID i ispišite ga na konzolu console.log(this.id); ));

Također možete koristiti svojstvo currentTarget (event.currentTarget) da dobijete trenutni element.

Faze (faze) događaja

Prije nego se događaj počne pojavljivati ​​(faza uspona), prvo prolazi kroz još 2 faze:

  • Faza 1 je faza uranjanja u element koji je generirao događaj. Oni. u ovoj fazi postoji kretanje odozgo prema dolje, tj. od objekta prozora do elementa. Ova faza se također naziva i faza presretanja.
  • Faza 2 je faza postizanja cilja, tj. element (objekt) koji je generirao događaj.

Uzimajući u obzir sve faze kroz koje jedan događaj prolazi, dobiva se sljedeća slika:

Modificirajmo gornji primjer skripte na sljedeći način:

Document.addEventListener("DOMContentLoaded", function() ( var allElements = document.getElementsByTagName("*"); for (var i=0; i

Treći parametar metoda addEventListener i removeEventListener određuje stupanj u kojem će događaj biti uhvaćen. Ako je ovaj parametar istinit, tada će događaj biti presretnut u fazi uranjanja (presretanja) događaja. A ako je parametar false, tada će događaj biti presretnut u fazi mjehurića. Da biste obradili događaj na samom cilju, možete koristiti metodu addEventListener s vrijednošću false ili true.

Pažnja: tijekom faze uranjanja (presretanja), događaje mogu presresti samo rukovatelji dodani pomoću metode addEventListener(). Rukovatelji dodani putem drugih metoda (HTML atribut ili putem JavaScripta koristeći svojstvo on[event]) mogu samo presresti događaje u fazi mjehurića.

Dohvaćanje elementa koji je generirao događaj

Da bi se dobio ciljni element, tj. element koji je generirao događaj mora koristiti ciljno svojstvo (event.target).

Razmotrite gornji primjer u kojem mijenjamo sadržaj elementa skripte u sljedeće:

Document.addEventListener("DOMContentLoaded", function() ( var elementBody = document.body; elementBody.addEventListener("click",function())( console.log(this.tagName + " - element koji je pozvao rukovatelja") ; console .log(event.currentTarget.tagName + " - element koji je pozvao rukovatelja");

Demonstrirajmo naš primjer klikom lijeve tipke miša na područje koje pripada jakom elementu:

Zdravo! U ovoj lekciji želim govoriti o tako važnom konceptu kao što je izranjanje i presretanje događaja. Bubbling je fenomen gdje ako kliknete na podređeni element, događaj se prenosi na njegovog roditelja.

Može biti vrlo korisno pri obradi velikih ugniježđenih popisa ili tablica; kako ne biste dodijelili rukovatelja događajima svakom elementu, možete dodijeliti jedan rukovatelj roditeljskom elementu, a događaj će se već proširiti na sve ugniježđene elemente u roditelju. Pogledajmo primjer.

Ovaj rukovatelj aktivirat će se ako kliknete na podoznaku ili :

Kliknite na EM, rukovatelj na DIV će raditi

Kao što vidite, kada kliknete na ugniježđeni em element, aktivira se rukovatelj na divu. Zašto se ovo događa? Čitajte dalje i saznajte.

Uspon

Dakle, osnovni princip uspona:

Kada postoji događaj bilo koje vrste, nije važno klikne li se mišem na element, događaj će se prvo pokrenuti na nadređenom elementu, a zatim će se duž lanca proširiti na sve ugniježđene elemente.

Na primjer, pretpostavimo da postoje 3 ugniježđena elementa FORM > DIV > P, s rukovateljem događaja na svakom:

tijelo * (margina: 10px; rub: 1px jednobojno plavo; ) FORM DIV

Bubbling osigurava klik na unutarnji element

Prvo će pozvati rukovatelja klikovima (ako postoji, naravno) na stvarnom

Ovaj se proces naziva mjehurićima, jer se čini da događaji "lebde" od unutarnjeg elementa prema gore kroz svoje roditelje, baš kao što mjehurić zraka lebdi u vodi, tako da možete pronaći i definiciju mjehurića, pa, to je samo od engleska riječ klokotanje - isplivati.

Pristup ciljnom elementu event.target

Kako bismo saznali na kojem elementu smo uhvatili ovaj ili onaj događaj, postoji metoda event.target. (pročitajte o objektu događaja).

  • event.target je stvarni izvorni element na kojem se događaj dogodio.
  • ovo je uvijek trenutni element do kojeg je bubbling došao, a rukovatelj je trenutno pokrenut na njemu.

Na primjer, ako imate instaliran samo jedan obrađivač form.onclick, on će "uhvatiti" sve klikove unutar obrasca. Štoviše, bez obzira gdje je klik unutra, on će i dalje iskočiti do elementa na kojem će rukovatelj raditi.

pri čemu:

  • ovo (=event.currentTarget) će uvijek biti sama forma, budući da je rukovatelj pokrenut na njoj.
  • event.target sadržavat će poveznicu na određeni element unutar obrasca, onaj koji je najviše ugniježđen na koji je došlo do klika.

U principu, to se može podudarati s event.target ako se klikne na obrazac i nema više elemenata u obrascu.

Zaustavljanje uspona

Tipično, mjehurić događaja ide ravno na vrh i doseže objekt korijenskog prozora.

Ali moguće je zaustaviti uspon na nekom srednjem elementu.

Kako biste zaustavili širenje, morate pozvati metodu event.stopPropagation().

Pogledajmo primjer: kada se klikne gumb, rukovatelj body.onclick neće raditi:

Klikni me

Ako element ima nekoliko instaliranih rukovatelja za isti događaj, tada će se svi izvršiti, čak i ako mjehurići prestanu.

Stoga će stopPropagation spriječiti daljnje širenje događaja, ali će svi rukovatelji raditi na elementu, ali ne i na sljedećem elementu.

Za zaustavljanje obrade trenutnog elementa preglednici podržavaju metodu event.stopImmediatePropagation(). Ova metoda ne samo da će spriječiti pojavu mjehurića, već će također zaustaviti obradu događaja na trenutnom elementu.

Ronjenje

U standardu, osim "uspona" događaja, postoji i "zaron".

Ronjenje je, za razliku od uspona, manje traženo, ali će i dalje biti korisno znati za to.

Dakle, postoje 3 faze događaja:

  • Događaj dolazi odozgo prema dolje. Ova faza se naziva "faza presretanja".
  • Događaj je dosegao određeni element. Ovo je "faza cilja".
  • Nakon svega počinje se nazirati događaj. Ovo je "faza uspona".
  • To je prikazano u standardu na sljedeći način:

    Dakle, kada kliknete na TD, događaj će putovati uzduž lanca roditelja, prvo dolje do elementa ("potone"), a zatim prema gore ("pops up"), koristeći odgovarajuće rukovatelje usput.

    Gore sam pisao samo o usponu, jer se ostale etape ne koriste i prolaze mimo nas nezapaženo.

    Voditelji ne znaju ništa o stupnju presretanja, ali počinju raditi od uspona.

    A da biste uhvatili događaj u fazi presretanja, samo trebate upotrijebiti:

    • Argument je istinit, tada će događaj biti presretnut na putu prema dolje.
    • Argument je netočan, tada će događaj biti uhvaćen prilikom mjehurića.
    Primjeri

    U primjeru na , ,

    Procesori su isti kao i prije, ali ovaj put u immersion fazi. Da biste vidjeli presretanje na djelu, kliknite na element u njemu

    Rukovatelji će raditi odozgo prema dolje: FORM → DIV → P.

    JS kod ovdje je:

    Var elems = document.querySelectorAll("form,div,p"); // priložite rukovatelja svakom elementu u fazi presretanja za (var i = 0; i< elems.length; i++) { elems[i].addEventListener("click", highlightThis, true); }


    Nitko vas ne sprječava da dodijelite rukovatelje za obje faze, ovako:

    Var elems = document.querySelectorAll("form,div,p"); za (var i = 0; i< elems.length; i++) { elems[i].addEventListener("click", highlightThis, true); elems[i].addEventListener("click", highlightThis, false); }

    Kliknite na unutarnji element

    Da biste vidjeli redoslijed događaja:
    Trebao bi biti FORM → DIV → P → P → DIV → FORM. Imajte na umu da element

    Sudjelovat će u obje faze.

    Rezultati
    • Kada se dogodi događaj, element na kojem se događaj dogodio označava se kao event.target.
    • Događaj se prvo pomiče prema dolje iz korijena dokumenta u event.target, usput pozivajući rukovatelje, koji se dostavljaju putem addEventListener(…., true).
    • Događaj se pomiče od event.target do početka dokumenta, usput poziva rukovatelje dostavljene putem addEventListener(…., false).

    Svaki rukovatelj imat će pristup svojstvima događaja:

    • event.target je najdublji element gdje se događaj zapravo dogodio.
    • event.currentTarget (=ovo) – element na kojem ovaj trenutak Pokrenut je samoprocesor (do kojeg je događaj "dospio").
    • event.eventPhase – u kojoj je fazi pokretač rukovatelja događajem (ron = 1, izron = 3).

    Širenje se može zaustaviti pozivanjem metode event.stopPropagation(), ali to se ne preporučuje, budući da vam događaj može trebati za najneočekivanije svrhe.

    Događaji su radnje ili pojave koje se događaju u sustavu koji programirate, o kojima vam sustav govori kako biste na njih mogli odgovoriti na neki način ako želite. Na primjer, ako korisnik klikne gumb na web stranici, možda biste željeli odgovoriti na tu radnju prikazivanjem okvira s informacijama. U ovom članku raspravljamo o nekim važnim konceptima vezanim uz događaje i gledamo kako oni funkcioniraju u preglednicima. Ovo neće biti iscrpna studija; samo ono što trebate znati u ovoj fazi.

    Preduvjeti: Cilj:
    Osnovna informatička pismenost, osnovno razumijevanje HTML i CSS, JavaScript prvi koraci.
    Razumjeti temeljnu teoriju događaja, kako rade u preglednicima i kako se događaji mogu razlikovati u različitim programskim okruženjima.
    Niz sretnih događaja

    Kao što je gore spomenuto, događaji su radnje ili pojave koje se događaju u sustavu koji programirate - sustav proizvodi (ili "ispaljuje") signal neke vrste kada se događaj dogodi, a također pruža mehanizam pomoću kojeg se neka vrsta radnje može automatski uzeti (to jest, neki kod se izvodi) kada se događaj dogodi. Na primjer, u zračnoj luci kada je uzletno-sletna staza slobodna za polijetanje, signal se šalje pilotu i kao rezultat toga, oni počinju upravljati avionom.

    U slučaju weba, događaji se pokreću unutar prozora preglednika i imaju tendenciju da budu pridruženi određenoj stavci koja se nalazi u njemu - to može biti jedan element, skup elemenata, HTML dokument učitan u trenutnoj kartici ili cijeli prozor preglednika. Postoji mnogo različitih vrsta događaja koji se mogu dogoditi, na primjer:

    • Korisnik klikne mišem preko određenog elementa ili pređe pokazivačem iznad određenog elementa.
    • Korisnik pritiska tipku na tipkovnici.
    • Korisnik mijenja veličinu ili zatvara prozor preglednika.
    • Šalje se obrazac.
    • Videozapis koji se reproducira, pauzira ili završava.
    • Došlo je do pogreške.

    Iz ovoga (i iz pogleda na MDN Event referencu) možete zaključiti da postoji puno događaja na koje se može odgovoriti.

    Svaki dostupni događaj ima rukovatelja događajem, koji je blok koda (obično JavaScript funkcija koju vi kao programer kreirate) koji će se pokrenuti kada se događaj pokrene. Kada je takav blok koda definiran da se pokreće kao odgovor na pokretanje događaja, kažemo da registriramo rukovatelja događajem. Imajte na umu da se rukovatelji događajima ponekad nazivaju slušateljima događaja - oni su prilično međusobno zamjenjivi za naše potrebe, iako strogo govoreći, rade zajedno. Slušatelj osluškuje događaj koji se događa, a rukovatelj je kod koji se pokreće kao odgovor na to što se događa.

    Napomena: Web događaji nisu dio osnovnog jezika JavaScript - definirani su kao dio API-ja ugrađenih u preglednik.

    Jednostavan primjer

    Pogledajmo jednostavan primjer da objasnimo što ovdje mislimo. Već ste vidjeli događaje i rukovatelje događajima koji se koriste u mnogim primjerima u ovom tečaju, ali ponovimo samo da učvrstimo svoje znanje. U sljedećem primjeru imamo single , koji kada se pritisne, mijenja pozadinu u nasumičnu boju:

    Promjena boje

    Gumb (margina: 10px);

    JavaScript izgleda ovako:

    Const btn = document.querySelector("gumb"); funkcija random(number) ( return Math.floor(Math.random() * (number+1)); ) btn.onclick = function() ( const rndCol = "rgb(" + random(255) + "," + random(255) + "," + random(255) + ")"; document.body.style.backgroundColor = rndCol )

    U ovom kodu pohranjujemo referencu na gumb unutar konstante pod nazivom btn, koristeći funkciju Document.querySelector(). Također definiramo funkciju koja vraća slučajni broj. Treći dio koda je rukovatelj događajima. Konstanta btn pokazuje na element, a ova vrsta objekta ima niz događaja koji se mogu pokrenuti na njemu, i stoga su dostupni rukovatelji događajima. Osluškujemo aktiviranje događaja klika, postavljajući svojstvo rukovatelja događajem onclick da bude jednako anonimnoj funkciji koja sadrži kod koji generira nasumične RGB boje i postavlja boju pozadine jednaku njoj.

    Ovaj se kod pokreće kad god se događaj klika aktivira na elementu, odnosno kad god korisnik klikne na njega.

    Primjer izlaza je sljedeći:

    Nisu to samo web stranice

    Još jedna stvar koju vrijedi spomenuti u ovom trenutku je da događaji nisu jedinstveni za JavaScript - većina programskih jezika ima neku vrstu modela događaja, a način na koji model funkcionira često se razlikuje od načina JavaScripta. Zapravo, model događaja u JavaScriptu za web stranice razlikuje se od modela događaja za JavaScript jer se koristi u drugim okruženjima.

    Inline rukovatelji događajima - nemojte ih koristiti

    U svom kodu također možete vidjeti obrazac poput ovog:

    Pritisnite me, funkcija bgChange() ( const rndCol = "rgb(" + random(255) + "," + random(255) + "," + random(255) + ")"; document.body.style.backgroundColor = rndCol )

    Najraniji način registriranja rukovatelja događajima pronađen na webu uključivao je HTML atribute rukovatelja događajima (ili ugrađene rukovatelje događajima) poput onog prikazanog gore - vrijednost atributa doslovno je JavaScript kod koji želite pokrenuti kada se događaj dogodi. Gornji primjer poziva funkciju definiranu unutar elementa na istoj stranici, ali također možete umetnuti JavaScript izravno unutar atributa, na primjer:

    pritisni me

    Možete pronaći ekvivalente HTML atributa za mnoga svojstva rukovatelja događajima; međutim, ne biste ih trebali koristiti - oni se smatraju lošom praksom. Moglo bi se činiti lakim za korištenje atributa rukovatelja događajima ako samo radite nešto jako brzo, ali oni vrlo brzo postaju neupravljivi i neučinkoviti.

    Za početak, nije dobra ideja miješati svoj HTML i JavaScript, jer postaje teško analizirati - bolje je držati svoj JavaScript na jednom mjestu; ako je u zasebnoj datoteci, možete ga primijeniti na više HTML dokumenata.

    Čak ni u jednoj datoteci, ugrađeni rukovatelji događajima nisu dobra ideja. Jedan gumb je OK, ali što ako imate 100 gumba? Morali biste dodati 100 atributa datoteci; to bi se vrlo brzo pretvorilo u održavanje. S JavaScriptom biste lako mogli kao noćna mora dodati funkciju rukovatelja događajima svim gumbima na stranici bez obzira koliko ih bilo, koristeći nešto poput ovaj:

    Const buttons = document.querySelectorAll("button"); za (neka je i = 0; i< buttons.length; i++) { buttons[i].onclick = bgChange; } buttons.forEach(function(button) { button.onclick = bgChange; });

    Napomena: Odvajanje vaše programske logike od vašeg sadržaja također čini vašu web stranicu prijateljskom prema tražilicama.

    addEventListener() i removeEventListener()

    Najnovija vrsta mehanizma događaja definirana je u Specifikaciji događaja razine 2 Document Object Model (DOM), koja preglednicima pruža novu funkciju - addEventListener() . Ovo funkcionira na sličan način kao svojstva rukovatelja događajima, ali je sintaksa očito drugačija. Mogli bismo prepisati naš primjer nasumične boje da izgleda ovako:

    Const btn = document.querySelector("gumb"); funkcija bgChange() ( const rndCol = "rgb(" + random(255) + "," + random(255) + "," + random(255) + ")"; document.body.style.backgroundColor = rndCol; ) btn.addEventListener("klik", bgPromijeni);

    Unutar funkcije addEventListener() specificiramo dva parametra - naziv događaja za koji želimo registrirati ovaj rukovatelj i kod koji sadrži funkciju rukovatelja koju želimo pokrenuti kao odgovor na njega. Imajte na umu da je savršeno prikladno staviti sav kod unutar funkcije addEventListener(), u anonimnu funkciju, poput ove:

    Btn.addEventListener("klik", funkcija() ( var rndCol = "rgb(" + random(255) + "," + random(255) + "," + random(255) + ")"; document.body .style.backgroundColor = rndCol);

    Ovaj mehanizam ima neke prednosti u odnosu na starije mehanizme o kojima smo ranije govorili. Za početak, postoji odgovarajuća funkcija, removeEventListener() , koja uklanja prethodno dodanog slušatelja. Na primjer, ovo bi uklonilo skup slušatelja u prvom bloku koda u ovom odjeljku:

    Btn.removeEventListener("klik", bgPromijeni);

    Ovo nije značajno za jednostavne, male programe, ali za veće, složenije programe može poboljšati učinkovitost čišćenja starih neiskorištenih rukovatelja događajima, na primjer, to vam omogućuje da isti gumb izvodi različite radnje u različitim okolnostima. sve što trebate učiniti je dodati ili ukloniti rukovatelje događajima prema potrebi.

    Drugo, također možete registrirati više rukovatelja za istog slušatelja. Sljedeća dva rukovatelja ne bi se oba primijenila:

    MojElement.onclick = funkcijaA; mojElement.onclick = funkcijaB;

    Drugi redak prepisuje vrijednost onclick postavljenu u prvom redu. Ovo bi, međutim, funkcioniralo:

    MyElement.addEventListener("klik", funkcijaA); myElement.addEventListener("klik", funkcijaB);

    Obje funkcije sada bi se pokrenule kada se element klikne.

    Osim toga, postoji niz drugih moćnih značajki i opcija dostupnih uz ovaj mehanizam događaja. Oni su malo izvan opsega ovog članka, ali ako želite pročitati o njima, pogledajte referentne stranice addEventListener() i removeEventListener().

    Koji mehanizam trebam koristiti?

    Od tri mehanizma, definitivno ne biste trebali koristiti atribute rukovatelja HTML događajima - oni su zastarjeli, i loše praksi, kao što je gore navedeno.

    Druga dva su relativno zamjenjiva, barem za jednostavne upotrebe:

    • Svojstva rukovatelja događajima imaju manje snage i mogućnosti, ali bolju kompatibilnost s više preglednika (podržana su još od Internet Explorer 8). Vjerojatno biste trebali početi s njima dok učite.
    • Događaji DOM razine 2 (addEventListener() itd.) su snažniji, ali također mogu postati složeniji i manje su podržani (podržani još od Internet Explorera 9). Također biste trebali eksperimentirati s njima i nastojati ih koristiti gdje god je to moguće.

    Glavne prednosti trećeg mehanizma su da možete ukloniti kod rukovatelja događajima ako je potrebno, koristeći removeEventListener() i možete dodati više slušatelja iste vrste elementima ako je potrebno. Na primjer, možete pozvati addEventListener("click", function() ( ... )) na elementu više puta, s različitim funkcijama navedenim u drugom argumentu. Ovo je nemoguće sa svojstvima rukovatelja događajima jer će svi sljedeći pokušaji postavljanja svojstva prebrisati prethodne, npr.:

    Element.onclick = funkcija1; element.onclick = funkcija2; itd.

    Napomena: Ako se od vas traži da u svom radu podržavate preglednike starije od Internet Explorera 8, mogli biste naići na poteškoće jer takvi stari preglednici koriste različite modele događaja od novijih preglednika. Ali nemojte se bojati, većina JavaScript biblioteka (na primjer jQuery) ima ugrađene funkcije koje apstrahiraju razlike između preglednika. Ne brinite o tome previše u ovoj fazi vašeg učenja.

    Ostali koncepti događaja

    U ovom odjeljku ukratko pokrivamo neke napredne koncepte koji su relevantni za događaje. U ovom trenutku nije važno u potpunosti razumjeti ove koncepte, ali oni mogu poslužiti za objašnjenje nekih obrazaca koda na koje ćete vjerojatno naići s vremena na vrijeme.

    Objekti događaja

    Ponekad unutar funkcije rukovatelja događajem možete vidjeti parametar naveden imenom kao što je događaj, evt ili jednostavno e. To se naziva objekt događaja i automatski se prosljeđuje rukovateljima događajima kako bi pružili dodatne značajke i informacije. Na primjer, ponovno malo prepišimo naš primjer nasumične boje:

    Funkcija bgChange(e) ( const rndCol = "rgb(" + random(255) + "," + random(255) + "," + random(255) + ")"; e.target.style.backgroundColor = rndCol console.log(e); btn.addEventListener("klik", bgChange);

    Ovdje možete vidjeti da uključujemo objekt događaja, e , u funkciju, au funkciji postavljamo stil boje pozadine na e.target - što je sam gumb. Ciljno svojstvo objekta događaja uvijek je referenca na element na kojem se događaj upravo dogodio. Dakle, u ovom primjeru postavljamo nasumičnu boju pozadine na gumbu, a ne na stranici.

    Napomena: Možete koristiti bilo koji naziv koji želite za objekt događaja - samo trebate odabrati naziv koji zatim možete koristiti za referencu unutar funkcije rukovatelja događajima. e/evt/event programeri najčešće koriste jer su kratki i lako se pamte. Uvijek je dobro biti dosljedan - sa samim sobom, a ako je moguće i s drugima.

    e.target je nevjerojatno koristan kada želite postaviti isti rukovatelj događajima na više elemenata i učiniti nešto sa svima njima kada se na njima dogodi događaj. Možete, na primjer, imati skup od 16 pločica koje nestaju kada se na njih klikne. Korisno je uvijek moći samo postaviti da stvar nestane kao e.target, umjesto da je morate odabrati na neki teži način. U sljedećem primjeru (pogledajte korisni-eventtarget.html za potpuni izvorni kod; također ga pogledajte uživo ovdje), stvaramo 16 elemenata koristeći JavaScript. Zatim ih sve odabiremo pomoću document.querySelectorAll() , zatim prolazimo kroz svaku od njih, dodajući onclick rukovatelj svakoj koja čini tako da se na svaku primjenjuje nasumična boja kada se klikne:

    Const divs = document.querySelectorAll("div"); za (neka je i = 0; i< divs.length; i++) { divs[i].onclick = function(e) { e.target.style.backgroundColor = bgChange(); } }

    Ispis je sljedeći (probajte kliknuti na njega - zabavite se):

    Skriveni primjer Primjer cilja cilja korisnog događaja div ( visina: 100 piksela; širina: 25%; float: lijevo; ) za (neka je i = 1; i
  • Olovka
  • Olovka
  • gumica za brisanje

  • Sada kada znamo da će svaki klik na gumb iskočiti kroz element ul.toolbar, pridružimo mu naš rukovatelj događajima. Srećom, već ga imamo:

    Var toolbar = document.querySelector(".toolbar"); toolbar.addEventListener("click", function(e) ( var button = e.target; if(!button.classList.contains("active")) button.classList.add("active"); else button.classList. ukloniti ("aktivno" ));
    Sada imamo puno čišći kod, a čak smo se riješili i petlji! Imajte na umu da smo zamijenili e.currentTarget s e.target. Razlog leži u činjenici da događaje obrađujemo na drugoj razini.

    e.target je stvarna meta događaja, gdje se probija kroz DOM, i odakle će se zatim pojaviti.
    e.currentTarget - trenutni element koji obrađuje događaj. U našem slučaju to je ul.toolbar.

    Poboljšani skočni događaji Trenutačno obrađujemo svaki klik na svaki element koji se pojavi preko ul.toolbar, ali naš testni uvjet je previše jednostavan. Što bi se dogodilo da imamo složeniji DOM koji uključuje ikone i elemente koji nisu dizajnirani da se na njih klikne?

    • Olovka
    • Olovka
    • gumica za brisanje

    Ups! Sada kada kliknemo li.separator ili ikonu, dodajemo mu klasu .active. Ovo u najmanju ruku nije dobro. Trebamo način filtriranja događaja kako bismo reagirali na element koji nam je potreban.

    Kreirajmo malu pomoćnu funkciju za ovo:

    Var delegat = function(criteria, listener) ( return function(e) ( var el = e.target; do ( if (!criteria(el)) continue; e.delegateTarget = el; listener.apply(this, arguments); return; ) while((el = el.parentNode));
    Naš pomoćnik radi dvije stvari. Prvo će iterirati po svakom elementu i njegovim roditeljima i provjeriti zadovoljavaju li uvjet proslijeđen u parametru kriterija. Ako element zadovoljava, pomoćnik dodaje polje objektu događaja pod nazivom delegateTarget, koje pohranjuje element koji zadovoljava naše uvjete. I onda poziva voditelja. Prema tome, ako niti jedan element ne zadovoljava uvjet, neće biti pozvan nijedan rukovatelj.

    Možemo ga koristiti ovako:

    Var toolbar = document.querySelector(".toolbar"); var buttonsFilter = function(elem) ( return elem.classList && elem.classList.contains("btn"); ); var buttonHandler = function(e) ( var button = e.delegateTarget; if(!button.classList.contains("active")) button.classList.add("active"); else button.classList.remove("active" ); toolbar.addEventListener("klik", delegat(buttonsFilter, buttonHandler));
    Upravo ono što je liječnik naredio: jedan rukovatelj događajima priključen na jedan element koji obavlja sav posao. Ali to čini samo za elemente koji su nam potrebni. I savršeno reagira na dodavanje i uklanjanje objekata iz DOM-a.

    Sažetak Ukratko smo pregledali osnove implementacije delegiranja (upravljanje skočnim prozorima) događaja na čisti JavaScript. Ovo je dobro jer ne trebamo generirati i priložiti hrpu rukovatelja za svaki element.

    Da želim od ovoga napraviti biblioteku ili koristiti kod u razvoju, dodao bih nekoliko stvari:

    Pomoćna funkcija za provjeru ispunjava li objekt kriterije u jedinstvenijem i funkcionalni oblik. Kao:

    Var kriterij = ( isElement: function(e) ( return e instanceof HTMLElement; ), hasClass: function(cls) ( return function(e) ( return kriterij.isElement(e) && e.classList.contains(cls); ) ) //Više kriterija);
    Djelomično korištenje pomoćnika također bi bilo korisno:

    Var partialDelgate = function(criteria) ( return function(handler) ( return delgate(criteria, handler); ) );
    Izvorni članak: Razumijevanje delegiranih JavaScript događaja
    (Od prevoditelja: moj prvi, sudite strogo.)

    Sretno kodiranje!



    reci prijateljima
    Pročitajte također