Uvod v pop-up dogodke. Napredno delo s predmetom Event v JavaScriptu Preklic bubblinga dogodkov js

V tej lekciji se bomo seznanili s konceptom mehurčkov dogodkov in pogledali, kako jih je mogoče prekiniti. Poleg tega bomo ugotovili, skozi katere druge faze (faze) gre dogodek, preden se začne pojavljati.

Oblaček dogodkov

Če pride do dogodka za neki element, začne "pop up", tj. pojavi pri starših, nato pri starih starših itd.

Iz tega sledi, da je dogodek, ki ga ustvari nek element, mogoče prestreči z uporabo obdelovalca na njegovem staršu, starem staršu itd.

Nastanek dogodka (mehurčka) bomo prikazali na naslednjem primeru:

Naslov

Nekaj ​​zelo pomembnega besedila

Odsek

Nekaj ​​besedila

Preostanek besedila

Napišimo majhen skript, s katerim bomo dodali obravnavo dogodka "klik" za vse elemente strani, kot tudi za objekte dokumenta in okna.

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); });

Ustvarimo stran HTML in vanjo vstavimo zgornjo kodo HTML. Scenarij napisan v JavaScript, vstavite pred zaključno oznako telesa. Po tem odprite novo ustvarjeno stran v spletnem brskalniku, pritisnite tipko F12 in pojdite na konzolo. Zdaj pa z levim klikom na območje, ki pripada močnemu elementu, poglejmo, kako se dogodek prikaže.

Kako prekiniti brbotanje dogodkov

Vzpon dogodka (mehurčka) lahko prekinemo. V tem primeru se ta dogodek ne bo sprožil za višje (nadrejene) elemente. Metoda, ki je zasnovana za zaustavitev širjenja dogodka (mehurčka), se imenuje stopPropagation().

Na primer, spremenimo naš zgornji primer, tako da se dogodek ne bo pojavil nad telesom: document.addEventListener("DOMContentLoaded", function() ( var allElements = document.getElementsByTagName("*"); for (var i=0 ; jaz

Nedvomno je navarjanje zelo priročno in arhitekturno pregledno. Ne prenehajte, razen če je to nujno potrebno.

Pridobivanje elementa, ki je poklical upravljalnik

Če želite pridobiti element (objekt) DOM, ki je poklical obravnavo dogodkov, morate uporabiti ključ beseda ta. dano ključna beseda(to) je na voljo samo v upravljalniku, če se na dogodek naročite z uporabo JavaScripta.

Na primer, v konzoli prikažimo ID elementa, ki je poklical obravnavo dogodkov:

Var myP = document.getElementById("myP"); myP.addEventListener("click",function())( //pridobi element DOM, ki je poklical obravnavo dogodkov - to //pridobi njegov ID in ga izpiši v konzolo console.log(this.id); ));

Za pridobitev trenutnega elementa lahko uporabite tudi lastnost currentTarget (event.currentTarget).

Faze (faze) dogodka

Preden se dogodek začne pojavljati (stopnja vzpona), gre najprej skozi še 2 stopnji:

  • Faza 1 je stopnja potopitve v element, ki je ustvaril dogodek. Tisti. na tej stopnji je gibanje od zgoraj navzdol, tj. od okenski objekt do elementa. Ta stopnja se imenuje tudi stopnja prestrezanja.
  • 2. stopnja je faza doseganja cilja, tj. element (objekt), ki je generiral dogodek.

Če upoštevamo vse faze, skozi katere gre dogodek, se prikaže naslednja slika:

Spremenimo zgornji primer skripta na naslednji način:

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

Tretji parameter metod addEventListener in removeEventListener določa stopnjo, na kateri bo dogodek ujet. če ta parameter je nastavljen na true , bo dogodek prestrežen na stopnji potopitve (prestrezanja) dogodka. In če je parameter false, bo dogodek prestrežen na stopnji brbotanja. Za obravnavo dogodka na samem cilju lahko uporabite metodo addEventListener kot pri vrednost false, in z vrednostjo true .

Pozor: med stopnjo potopitve (prestrezanja) lahko dogodke prestrežejo samo upravljalci, dodani z metodo addEventListener(). Rukovniki, dodani z drugimi metodami ( HTML atribut ali prek JavaScripta z uporabo lastnosti on[event]) lahko prestreže dogodke samo na stopnji brbotanja.

Pridobivanje elementa, ki je ustvaril dogodek

Da bi dobili ciljni element, tj. element, ki je ustvaril dogodek, mora uporabljati lastnost cilja (event.target).

Razmislite o zgornjem primeru, v katerem spremenimo vsebino elementa skripta v naslednje:

Document.addEventListener("DOMContentLoaded", function() ( var elementBody = document.body; elementBody.addEventListener("click",function())( console.log(this.tagName + " - element, ki je poklical obravnavo") ; konzola .log(event.currentTarget.tagName + " - element, ki je poklical obravnavo"); console.log(event.target.tagName + " - element, ki je ustvaril dogodek"); ),false); )) ;

Predstavimo naš primer z levim klikom v območju, ki pripada močnemu elementu:

Vse se je začelo z uporabo JavaScripta in razredov.

Vendar imam problem. Želel sem uporabiti nekaj, kar se imenuje Bubble Events, vendar sem želel tudi zmanjšati odvisnosti, ki bi jih moral vnesti. Nisem se hotel povezati knjižnice jQuery za "ta mali test", samo za uporabo pojavnih dogodkov.

Oglejmo si podrobneje, kaj so dogodki nazdravljanja, kako delujejo in nekaj načinov za njihovo izvedbo.

V redu, v čem je torej problem? Poglejmo preprost primer:

Recimo, da imamo seznam gumbov. Vsakič, ko kliknem enega od njih, bi moral postati "aktiven". Po ponovnem pritisku se mora gumb vrniti v prvotno stanje.

Začnimo s HTML-jem:

  • Svinčnik
  • Pero
  • radirka

Lahko bi uporabil standardni obravnavo dogodkov JavaScript, kot je ta:

For(var i = 0; i< buttons.length; i++) { var button = buttons[i]; button.addEventListener("click", function() { if(!button.classList.contains("active")) button.classList.add("active"); else button.classList.remove("active"); }); }
Izgleda dobro ... Ampak ne bo šlo. Avtor: vsaj, ne tako kot pričakujemo.

Zapiranje zmaga Za tiste, ki poznajo malo funkcionalnega JavaScripta, je težava očitna.

Za ostalo bom na kratko razložil - funkcija obdelovalca je zaklenjena na spremenljivko gumba. Vendar je to ena sama spremenljivka in se prepiše pri vsaki ponovitvi.

V prvi ponovitvi se spremenljivka nanaša na prvi gumb. V naslednjem - v drugo in tako naprej. Ko pa uporabnik klikne na gumb, se je zanka že končala in spremenljivka gumba se nanaša na zadnji gumb, ki zanj vedno pokliče obravnavo dogodkov. Motnja.

Kar potrebujemo, je ločen kontekst za vsako funkcijo:

Var buttons = document.querySelectorAll(".gumb orodne vrstice"); var createToolbarButtonHandler = function(button) ( return function() ( if(!button.classList.contains("active")) button.classList.add("active"); else button.classList.remove("active"); ); ); for(var i = 0; i< buttons.length; i++) { buttons[i].addEventListener("click", createToolBarButtonHandler(buttons[i])); }
Precej bolje! In kar je najpomembneje, deluje pravilno. Ustvarili smo funkcijo createToolbarButtonHandle, ki vrne obravnavo dogodkov. Nato za vsak gumb pritrdimo svoj ročaj.

Torej v čem je problem? Izgleda dobro in deluje. Kljub temu lahko svojo kodo še izboljšamo.

Prvič, ustvarimo preveč upravljavcev. Za vsak gumb v .toolbaru ustvarimo funkcijo in jo povežemo kot obravnavo dogodkov. Pri treh gumbih je poraba pomnilnika zanemarljiva.

Če pa imamo kaj takega:

  • Foo
  • Bar
  • // ...še 997 elementov...
  • baz

potem računalnik seveda ne bo eksplodiral zaradi prelivanja. Vendar pa naša poraba pomnilnika še zdaleč ni idealna. Namenimo ga ogromno, čeprav lahko brez njega. Ponovno napišimo kodo, da bomo lahko isto funkcijo uporabili večkrat.

Namesto sklicevanja na spremenljivko gumba, da bi spremljali, kateri gumb smo kliknili, lahko uporabimo objekt dogodka, ki se kot prvi argument posreduje vsakemu obdelovalcu dogodkov.

Objekt Event vsebuje nekaj podatkov o dogodku. V našem primeru nas zanima polje currentTarget. Iz njega bomo dobili povezavo do elementa, ki smo ga kliknili:

Var toolbarButtonHandler = function(e) ( var button = e.currentTarget; if(!button.classList.contains("active")) button.classList.add("active"); else button.classList.remove("active" ); ); for(var i = 0; i< buttons.length; i++) { button.addEventListener("click", toolbarButtonHandler); }
Super! Ne samo, da smo vse poenostavili na eno samo funkcijo, ki se uporablja večkrat, našo kodo smo naredili tudi bolj berljivo, tako da smo odstranili nepotrebno funkcijo generatorja.

Vendar smo še vedno lahko boljši.

Recimo, da smo na list dodali nekaj gumbov po izvedbi kode. Potem bi morali dodati tudi obdelovalce dogodkov za vsakega od njih. In morali bi shraniti povezavo do tega upravljalnika in povezave z drugih mest. Ne izgleda preveč mamljivo.

Morda obstaja drug pristop?

Začnimo z razumevanjem delovanja dogodkov in njihovega premikanja po našem DOM-u.

Kako jih večina deluje? Ko uporabnik klikne na element, se ustvari dogodek, ki o tem obvesti aplikacijo. Potovanje vsakega dogodka poteka v treh fazah:
  • Faza prestrezanja
  • Dogodek se zgodi na ciljnem elementu
  • Faza vzpona
  • Opomba: vsi dogodki ne gredo skozi stopnjo prestrezanja ali mehurčkov; nekateri se ustvarijo takoj na elementu. Vendar je to precej izjema od pravila.

    Dogodek je ustvarjen zunaj dokumenta in nato zaporedno premaknjen skozi hierarhijo DOM do ciljnega elementa. Ko doseže svoj cilj, se dogodek pridobi iz elementa DOM na enak način.

    Tukaj je naša predloga HTML:

    • Gumb A
    • Gumb B
    • Gumb C

    Ko uporabnik klikne gumb A, potuje dogodek takole:

    Začetek
    | #dokument
    | Faza prestrezanja
    | HTML
    | TELO
    | UL
    | LI#li_1
    | Gumb A< - Событие возникает для целевого элемента
    | Faza vzpona
    | LI#li_1
    | UL
    | TELO
    | HTML
    v #dokument

    Upoštevajte, da lahko sledimo poti, ki jo dogodek opravi, da doseže ciljni element. V našem primeru smo za vsak pritisk na gumb lahko prepričani, da se bo dogodek vrnil v mehurček in šel skozi svojega nadrejenega elementa - ul element. To lahko uporabimo in implementiramo pojavne dogodke.

    Bubble dogodki Bubble dogodki so tisti dogodki, ki so pripeti nadrejenemu elementu, vendar se izvedejo le, če izpolnjujejo nek pogoj.

    Vzemimo našo orodno vrstico kot konkreten primer:

    Ul class="orodna vrstica">

  • Svinčnik
  • Pero
  • radirka

  • Zdaj, ko vemo, da se bo vsak klik na gumb pojavil skozi element ul.toolbar, mu priložimo naš upravljalnik dogodkov. Na srečo ga že imamo:

    Var toolbar = document.querySelector(".toolbar"); toolbar.addEventListener("klik", funkcija(e) ( var button = e.target; if(!button.classList.contains("active")) button.classList.add("active"); else button.classList. odstrani ("aktivno"); ));
    Zdaj imamo veliko čistejšo kodo in celo znebili smo se zank! Vendar upoštevajte, da smo e.currentTarget zamenjali z e.target. Razlog je v tem, da procesiramo dogodke na drugačni ravni.

    e.target je dejanska tarča dogodka, kjer se prebija skozi DOM in od koder se nato dvigne.
    e.currentTarget - trenutni element, ki obravnava dogodek. V našem primeru je to ul.toolbar.

    Izboljšani dogodki oblačkov ta trenutek Obravnavamo vsak klik na vsak element, ki se prikaže prek ul.toolbar, vendar je naš pogoj preverjanja preenostaven. Kaj bi se zgodilo, če bi imeli bolj zapleten DOM, ki bi vključeval ikone in elemente, ki niso zasnovani za klikanje?

    • Svinčnik
    • Pero
    • radirka

    Ups! Zdaj, ko kliknemo li.separator ali ikono, mu dodamo razred .active. Vsaj to ni dobro. Potrebujemo način filtriranja dogodkov, tako da se odzovemo na element, ki ga potrebujemo.

    Za to ustvarimo majhno pomožno funkcijo:

    Var delegate = 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 dela dve stvari. Najprej bo ponovil vsak element in njegove starše ter preveril, ali izpolnjujejo pogoj, posredovan v parametru kriterijev. Če element ustreza, pomočnik doda polje v objekt dogodka z imenom delegateTarget, ki shrani element, ki izpolnjuje naše pogoje. In nato pokliče skrbnika. V skladu s tem, če noben element ne izpolnjuje pogoja, ne bo poklican noben upravljavec.

    Lahko ga uporabimo takole:

    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));
    Ravno to, kar je naročil zdravnik: en upravljavec dogodkov, pritrjen na en element, ki opravi vse delo. Vendar to počne samo za elemente, ki jih potrebujemo. In popolnoma se odziva na dodajanje in odstranjevanje predmetov iz DOM.

    Povzetek Na kratko smo pregledali osnove izvajanja dogodkov delegiranja (ravnanje s pojavnimi okni) na čisti JavaScript. To je dobro, ker nam ni treba ustvariti in priložiti kopice upravljavcev za vsak element.

    Če bi želel iz tega narediti knjižnico ali uporabiti kodo v razvoju, bi dodal nekaj stvari:

    Pomožna funkcija za preverjanje, ali objekt izpolnjuje kriterije v bolj enotni in funkcionalni obliki. Všeč mi je:

    Kriterij var = ( isElement: function(e) ( return e instanceof HTMLElement; ), hasClass: function(cls) ( return function(e) ( return критерии.isElement(e) && e.classList.contains(cls); ) ) //Več meril);
    Koristna bi bila tudi delna uporaba pomočnika:

    Var partialDelgate = function(criteria) ( return function(handler) ( return delgate(criteria, handler); ) );
    Izvirni članek: Razumevanje pooblaščenih dogodkov JavaScript
    (Od prevajalca: moj prvi, sodite strogo.)

    Veselo kodiranje!

    Dogodki so dejanja ali dogodki, ki se zgodijo v sistemu, ki ga programirate, o katerih vam sistem sporoči, da se lahko nanje na nek način odzovete, če želite. Na primer, če uporabnik klikne gumb na spletni strani, se boste morda želeli na to dejanje odzvati s prikazom polja z informacijami. V tem članku razpravljamo o nekaterih pomembnih konceptih, povezanih z dogodki, in si ogledamo, kako delujejo v brskalnikih. To ne bo izčrpna študija; samo kaj potrebujete vedeti na tej stopnji.

    Predpogoji: Cilj:
    Osnovna računalniška pismenost, osnovno razumevanje HTML in CSS, JavaScript prvi koraki.
    Razumeti temeljno teorijo dogodkov, kako delujejo v brskalnikih in kako se dogodki lahko razlikujejo v različnih programskih okoljih.
    Niz srečnih dogodkov

    Kot že omenjeno, so dogodki dejanja ali dogodki, ki se zgodijo v sistemu, ki ga programirate - sistem ustvari (ali "sproži") nekakšen signal, ko pride do dogodka, in nudi tudi mehanizem, s katerim se lahko nekakšno dejanje izvede. samodejno sprejet (tj. neka koda se izvaja), ko pride do dogodka. Na primer na letališču, ko je vzletno-pristajalna steza prosta za vzlet letala, se pilotu sporoči signal in posledično začne pilotirati letalo.

    V primeru spleta se dogodki sprožijo znotraj okna brskalnika in so običajno pripeti na določen element, ki se nahaja v njem - to je lahko en sam element, nabor elementov, dokument HTML, naložen v trenutnem zavihku, ali celotno okno brskalnika. Obstaja veliko različnih vrst dogodkov, ki se lahko zgodijo, na primer:

    • Uporabnik, ki z miško klikne na določen element ali se s kazalcem pomakne na določen element.
    • Uporabnik pritisne tipko na tipkovnici.
    • Uporabnik spremeni velikost ali zapre okno brskalnika.
    • Oddaja obrazca.
    • Videoposnetek, ki se predvaja ali je zaustavljen ali se predvajanje konča.
    • Prihaja do napake.

    Iz tega (in s pogledom na referenco MDN Event) lahko ugotovite, da obstaja veliko dogodkov, na katere se je mogoče odzvati.

    Vsak razpoložljiv dogodek ima upravljalnik dogodkov, ki je blok kode (običajno funkcija JavaScript, ki jo ustvarite kot programer), ki se bo zagnal, ko se dogodek sproži. Ko je tak blok kode definiran za izvajanje kot odgovor na sprožitev dogodka, pravimo, da registriramo obdelovalca dogodkov. Upoštevajte, da se obdelovalci dogodkov včasih imenujejo poslušalci dogodkov - za naše namene so precej zamenljivi, čeprav strogo gledano delujejo skupaj. Poslušalec prisluhne dogajanju dogodka, upravljavec pa je koda, ki se zažene kot odgovor na dogodek.

    Opomba: Spletni dogodki niso del osnovnega jezika JavaScript – definirani so kot del API-jev, vgrajenih v brskalnik.

    Preprost primer

    Oglejmo si preprost primer, da pojasnimo, kaj mislimo tukaj. Videli ste že dogodke in obdelovalce dogodkov, uporabljene v številnih primerih v tem tečaju, vendar povzamemo, da utrdimo svoje znanje. V naslednjem primeru imamo single , ki ob pritisku spremeni ozadje v naključno barvo:

    Spremeni barvo

    Gumb (rob: 10px);

    JavaScript izgleda takole:

    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; )

    V tej kodi shranimo sklic na gumb znotraj konstante, imenovane btn, z uporabo funkcije Document.querySelector(). Definiramo tudi funkcijo, ki vrne naključno število. Tretji del kode je upravljalnik dogodkov. Konstanta btn kaže na element in ta vrsta objekta ima številne dogodke, ki se lahko sprožijo na njem, in zato so na voljo obdelovalci dogodkov. Prisluškujemo sprožitvi dogodka klika tako, da nastavimo lastnost obdelovalca dogodka onclick na enako anonimno funkcijo, ki vsebuje kodo, ki generira naključno barvo RGB in nastavi barvo ozadja, ki je enaka njej.

    Ta koda se zažene vsakič, ko se dogodek klika sproži na elementu, to je vsakič, ko uporabnik klikne nanj.

    Primer izhoda je naslednji:

    To niso samo spletne strani

    Druga stvar, ki jo je vredno omeniti na tej točki, je, da dogodki niso edinstveni za JavaScript - večina programskih jezikov ima nekakšen model dogodkov in način delovanja modela se pogosto razlikuje od načina JavaScripta. Pravzaprav je model dogodkov v JavaScriptu za spletne strani se razlikuje od modela dogodkov za JavaScript, saj se uporablja v drugih okoljih.

    Vgrajeni obdelovalci dogodkov – ne uporabljajte jih

    V svoji kodi boste morda videli tudi vzorec, kot je ta:

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

    Najzgodnejša metoda registracije obdelovalcev dogodkov, ki so jo našli na spletu, je vključevala atribute HTML obdelovalca dogodkov (ali vgrajene obdelovalce dogodkov), kot je prikazan zgoraj - vrednost atributa je dobesedno koda JavaScript, ki jo želite zagnati, ko pride do dogodka. Zgornji primer prikliče funkcijo, definirano znotraj elementa na isti strani, vendar lahko JavaScript vstavite tudi neposredno v atribut, na primer:

    Pritisni me

    Najdete lahko enakovrednosti atributov HTML za številne lastnosti obdelovalnika dogodkov; vendar jih ne bi smeli uporabljati - veljajo za slabo prakso. Morda se zdi enostavno uporabljati atribute za obravnavo dogodkov, če le počnete nekaj zelo hitro, vendar zelo hitro postanejo neobvladljivi in ​​neučinkoviti.

    Za začetek ni dobra ideja, da pomešate svoj HTML in JavaScript, saj ga je težko razčleniti – bolje je, da imate ves JavaScript na enem mestu; če je v ločeni datoteki, ga lahko uporabite za več dokumentov HTML.

    Tudi v eni sami datoteki vgrajeni obdelovalci dogodkov niso dobra ideja. En gumb je v redu, kaj pa če bi imeli 100 gumbov? Datoteki bi morali dodati 100 atributov; to bi se zelo hitro spremenilo v vzdrževanje. Z JavaScriptom bi lahko zlahka dodali funkcijo obdelovalca dogodkov vsem gumbom na strani, ne glede na to, koliko jih je, z uporabo nečesa podobnega to:

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

    Opomba: Ločevanje vaše programske logike od vaše vsebine naredi tudi vaše spletno mesto bolj prijazno do iskalnikov.

    addEventListener() in removeEventListener()

    Najnovejša vrsta mehanizma dogodkov je opredeljena v specifikaciji dogodkov ravni 2 Document Object Model (DOM), ki brskalnikom ponuja novo funkcijo - addEventListener() . To deluje na podoben način kot lastnosti obdelovalnika dogodkov, vendar je sintaksa očitno drugačna. Primer naključne barve bi lahko prepisali takole:

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

    Znotraj funkcije addEventListener() določimo dva parametra - ime dogodka, za katerega želimo registrirati ta obravnavalec, in kodo, ki sestavlja funkcijo obdelovalca, ki jo želimo zagnati kot odgovor nanj. Upoštevajte, da je povsem primerno, da vso kodo postavite v funkcijo addEventListener() v anonimni funkciji, kot je ta:

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

    Ta mehanizem ima nekaj prednosti pred starejšimi mehanizmi, o katerih smo govorili prej. Za začetek obstaja nasprotna funkcija, removeEventListener(), ki odstrani predhodno dodanega poslušalca. S tem bi na primer odstranili nabor poslušalcev v prvem bloku kode v tem razdelku:

    Btn.removeEventListener("klik", bgSpremeni);

    To ni pomembno za preproste, majhne programe, toda za večje, bolj zapletene programe lahko izboljša učinkovitost čiščenja starih neuporabljenih obdelovalcev dogodkov. Poleg tega vam na primer omogoča, da isti gumb izvaja različna dejanja v različnih okoliščinah - vse kar morate storiti je, da dodate ali odstranite obdelovalce dogodkov, kot je primerno.

    Drugič, registrirate lahko tudi več upravljavcev za istega poslušalca. Naslednja dva upravljalnika ne bi bila uporabljena oba:

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

    Druga vrstica prepiše vrednost onclick, ki jo je nastavila prva vrstica. To pa bi delovalo:

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

    Obe funkciji bi se zdaj zagnali, ko bi element kliknili.

    Poleg tega so s tem mehanizmom dogodkov na voljo številne druge zmogljive funkcije in možnosti. Te so nekoliko izven obsega tega članka, a če želite o njih prebrati, si oglejte referenčni strani addEventListener() in removeEventListener().

    Kateri mehanizem naj uporabim?

    Od treh mehanizmov zagotovo ne bi smeli uporabljati atributov obdelovalnika dogodkov HTML - ti so zastareli in slaba praksa, kot je omenjeno zgoraj.

    Druga dva sta razmeroma zamenljiva, vsaj za preproste uporabe:

    • Lastnosti obdelovalca dogodkov imajo manj moči in možnosti, vendar boljšo združljivost med brskalniki (podprto že v internet Explorer 8). Verjetno bi morali začeti s temi, ko se učite.
    • Dogodki ravni 2 DOM (addEventListener() itd.) so zmogljivejši, vendar lahko postanejo tudi bolj zapleteni in so slabše podprti (podprti že v Internet Explorerju 9). Prav tako bi morali eksperimentirati s temi in si jih prizadevati uporabiti, kjer je to mogoče.

    Glavne prednosti tretjega mehanizma so, da lahko po potrebi odstranite kodo za obravnavo dogodkov z uporabo removeEventListener() in elementom po potrebi dodate več poslušalcev istega tipa. Na primer, elementu lahko večkrat pokličete addEventListener("click", function() ( ... )) z različnimi funkcijami, podanimi v drugem argumentu. To je nemogoče z lastnostmi obdelovalnika dogodkov, ker bodo vsi nadaljnji poskusi nastavitve lastnosti prepisali prejšnje, npr.:

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

    Opomba: če boste pri svojem delu morali podpirati brskalnike, starejše od Internet Explorerja 8, lahko naletite na težave, saj takšni stari brskalniki uporabljajo drugačne modele dogodkov od novejših brskalnikov. Toda brez strahu, večina knjižnic JavaScript (na primer jQuery) ima vgrajene funkcije, ki abstrahirajo razlike med brskalniki. Naj vas to ne skrbi preveč na tej stopnji vaše učne poti.

    Drugi koncepti dogodkov

    V tem razdelku na kratko pokrivamo nekatere napredne koncepte, ki so pomembni za dogodke. Na tej točki ni pomembno, da te koncepte v celoti razumete, lahko pa služijo za razlago nekaterih vzorcev kode, na katere boste verjetno občasno naleteli.

    Prireditveni objekti

    Včasih lahko znotraj funkcije obdelovalnika dogodkov vidite parameter, določen z imenom, kot je dogodek, evt ali preprosto e. To se imenuje objekt dogodka in se samodejno posreduje obdelovalcem dogodkov za zagotavljanje dodatnih funkcij in informacij. Na primer, ponovno nekoliko prepišimo naš primer naključne barve:

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

    Tukaj lahko vidite, da smo v funkcijo vključili objekt dogodka, e , in v funkciji, ki nastavi barvni slog ozadja na e.target - kar je sam gumb. Ciljna lastnost objekta dogodka je vedno sklic na element, na katerem se je pravkar zgodil dogodek. V tem primeru torej nastavljamo naključno barvo ozadja na gumbu, ne na strani.

    Opomba: za predmet dogodka lahko uporabite poljubno ime - samo izbrati morate ime, ki ga lahko nato uporabite za sklicevanje nanj znotraj funkcije obdelovalca dogodkov. e/evt/event najpogosteje uporabljajo razvijalci, ker so kratki in si jih je lahko zapomniti. Vedno je dobro biti dosleden – do sebe in do drugih, če je le mogoče.

    e.target je neverjetno uporaben, ko želite nastaviti isti obravnavalec dogodkov na več elementih in narediti nekaj za vse, ko se na njih zgodi dogodek. Morda imate na primer niz 16 ploščic, ki izginejo, ko nanje kliknete. Koristno je, da lahko vedno samo nastavite, da stvar izgine kot e.target, namesto da bi jo morali izbrati na kakšen težji način. V naslednjem primeru (oglejte si korisni-eventtarget.html za celotno izvorno kodo; oglejte si tudi, kako deluje tukaj) ustvarimo 16 elementov z uporabo JavaScripta. Nato jih vse izberemo z uporabo document.querySelectorAll() , nato pa se pobrskamo po vsakem od njih in vsakemu dodamo obravnavo onclick, ki omogoča, da se ob kliku na vsakega uporabi naključna barva:

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

    Rezultat je naslednji (poskusite klikati nanj - zabavajte se):

    Skriti primer Primer cilja uporabnega dogodka div ( višina: 100 slikovnih pik; širina: 25 %; lebdeče: levo; ) za (naj i = 1; i
  • Svinčnik
  • Pero
  • radirka

  • Zdaj, ko vemo, da se bo vsak klik na gumb pojavil skozi element ul.toolbar, mu priložimo naš upravljalnik dogodkov. Na srečo ga že imamo:

    Var toolbar = document.querySelector(".toolbar"); toolbar.addEventListener("klik", funkcija(e) ( var button = e.target; if(!button.classList.contains("active")) button.classList.add("active"); else button.classList. odstrani ("aktivno"); ));
    Zdaj imamo veliko čistejšo kodo in celo znebili smo se zank! Vendar upoštevajte, da smo e.currentTarget zamenjali z e.target. Razlog je v tem, da procesiramo dogodke na drugačni ravni.

    e.target je dejanska tarča dogodka, kjer se prebija skozi DOM in od koder se nato dvigne.
    e.currentTarget - trenutni element, ki obravnava dogodek. V našem primeru je to ul.toolbar.

    Izboljšani pojavni dogodki Trenutno obravnavamo vsak klik na vsak element, ki se pojavi prek ul.toolbar, vendar je naš pogoj preverjanja preenostaven. Kaj bi se zgodilo, če bi imeli bolj zapleten DOM, ki bi vključeval ikone in elemente, ki niso zasnovani za klikanje?

    • Svinčnik
    • Pero
    • radirka

    Ups! Zdaj, ko kliknemo li.separator ali ikono, mu dodamo razred .active. Vsaj to ni dobro. Potrebujemo način filtriranja dogodkov, tako da se odzovemo na element, ki ga potrebujemo.

    Za to ustvarimo majhno pomožno funkcijo:

    Var delegate = 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 dela dve stvari. Najprej bo ponovil vsak element in njegove starše ter preveril, ali izpolnjujejo pogoj, posredovan v parametru kriterijev. Če element ustreza, pomočnik doda polje v objekt dogodka z imenom delegateTarget, ki shrani element, ki izpolnjuje naše pogoje. In nato pokliče skrbnika. V skladu s tem, če noben element ne izpolnjuje pogoja, ne bo poklican noben upravljavec.

    Lahko ga uporabimo takole:

    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));
    Ravno to, kar je naročil zdravnik: en upravljavec dogodkov, pritrjen na en element, ki opravi vse delo. Vendar to počne samo za elemente, ki jih potrebujemo. In popolnoma se odziva na dodajanje in odstranjevanje predmetov iz DOM.

    Povzetek Na kratko smo si ogledali osnove izvajanja dogodkov delegiranja (ravnanje s pojavnimi okni) v čistem JavaScriptu. To je dobro, ker nam ni treba ustvariti in priložiti kopice upravljavcev za vsak element.

    Če bi želel iz tega narediti knjižnico ali uporabiti kodo v razvoju, bi dodal nekaj stvari:

    Pomožna funkcija za preverjanje, ali objekt izpolnjuje kriterije v bolj enotni in funkcionalni obliki. Všeč mi je:

    Kriterij var = ( isElement: function(e) ( return e instanceof HTMLElement; ), hasClass: function(cls) ( return function(e) ( return критерии.isElement(e) && e.classList.contains(cls); ) ) //Več meril);
    Koristna bi bila tudi delna uporaba pomočnika:

    Var partialDelgate = function(criteria) ( return function(handler) ( return delgate(criteria, handler); ) );
    Izvirni članek: Razumevanje pooblaščenih dogodkov JavaScript
    (Od prevajalca: moj prvi, sodite strogo.)

    Veselo kodiranje!

    Zdravo! V tej lekciji želim govoriti o tako pomembnem konceptu, kot je pojavljanje in prestrezanje dogodkov. Bubbling je pojav, pri katerem se dogodek prenese na njegov nadrejeni element, če kliknete podrejeni element.

    Lahko je zelo uporabno pri obdelavi velikih ugnezdenih seznamov ali tabel, tako da ne dodelite obdelovalca dogodka vsakemu elementu, lahko dodelite enega obdelovalca nadrejenemu elementu in dogodek se bo že razširil na vse ugnezdene elemente v nadrejenem. Poglejmo si primer.

    Ta upravljalnik se sproži, če kliknete podoznako ali:

    Kliknite na EM, upravljalnik na DIV bo deloval

    Kot lahko vidite, se ob kliku na ugnezdeni element em sproži obravnava elementa div. Zakaj se to dogaja? Preberite in ugotovite.

    Vzpon

    Torej osnovno načelo vzpona:

    Ko pride do kakršnega koli dogodka, ni pomembno, ali z miško kliknete na element, dogodek se bo najprej sprožil na nadrejenem elementu, nato pa se bo po verigi razširil na vse ugnezdene elemente.

    Na primer, predpostavimo, da obstajajo 3 ugnezdeni elementi FORM > DIV > P, na vsakem pa je obravnavalec dogodkov:

    body * (rob: 10px; obroba: 1px neprekinjeno modra; ) FORM DIV

    Bubbling zagotavlja, da kliknete na notranji element

    Najprej bo dejanski poklical upravljalnik klikov (če seveda obstaja).

    Ta proces se imenuje vzpon, ker se zdi, da dogodki "lebdijo" od notranjega elementa navzgor skozi svoje starše, tako kot zračni mehurček lebdi v vodi, tako da lahko najdete tudi definicijo mehurčkov, no, to je samo iz angleščine beseda bubbling - lebdeti.

    Dostop do ciljnega elementa event.target

    Da bi ugotovili, na katerem elementu smo ujeli ta ali oni dogodek, obstaja metoda event.target. (preberite o objektu dogodka).

    • event.target je dejanski izvorni element, na katerem se je zgodil dogodek.
    • to je vedno trenutni element, ki ga je brbotanje doseglo, in na njem se trenutno izvaja upravljalnik.

    Na primer, če imate nameščen samo en obdelovalnik form.onclick, potem bo "ujel" vse klike znotraj obrazca. Še več, ne glede na to, kje je klik znotraj, se bo še vedno pojavil do elementa, na katerem bo deloval upravljalnik.

    pri čemer:

    • to (=event.currentTarget) bo vedno sam obrazec, saj je bil na njem sprožen upravljalnik.
    • event.target bo vseboval povezavo do določenega elementa v obrazcu, najbolj ugnezdenega, na katerega je prišlo do klika.

    Načeloma lahko to sovpada z event.target, če obrazec kliknemo in v obrazcu ni več elementov.

    Ustavitev vzpona

    Običajno gre brbotanje dogodka naravnost na vrh in doseže predmet korenskega okna.

    Je pa možno vzpon prekiniti na kakšnem vmesnem elementu.

    Če želite ustaviti širjenje, morate poklicati metodo event.stopPropagation().

    Poglejmo primer: ko kliknete gumb, rutina za obravnavo body.onclick ne bo delovala:

    Kliknite me

    Če ima element nameščenih več rokovalcev za isti dogodek, bodo izvedeni vsi, tudi če se brbotanje ustavi.

    Tako bo stopPropagation preprečil nadaljnje širjenje dogodka, vendar bodo vsi upravljavci delovali na elementu, ne pa tudi na naslednjem elementu.

    Če želite ustaviti obdelavo trenutnega elementa, brskalniki podpirajo metodo event.stopImmediatePropagation(). Ta metoda ne bo samo preprečila mehurčkov, ampak bo tudi ustavila obdelavo dogodkov na trenutnem elementu.

    Potapljanje

    V standardu je poleg "vzpona" dogodkov tudi "potop".

    Potapljanje, za razliko od vzpona, je manj povpraševanje, vendar bo še vedno koristno vedeti o tem.

    Torej obstajajo 3 stopnje dogodka:

  • Dogodek prihaja od zgoraj navzdol. Ta stopnja se imenuje "stopnja prestrezanja".
  • Dogodek je dosegel določen element. To je "faza cilja".
  • Po vsem se začne pojavljati dogodek. To je "faza vzpona".
  • To je v standardu prikazano na naslednji način:

    Tako, ko kliknete na TD, bo dogodek potoval vzdolž verige staršev, najprej navzdol do elementa (»potone«), nato pa navzgor (»pops up«), pri čemer bodo na poti ustrezno uporabljeni upravljalci.

    Zgoraj sem pisal samo o vzponu, ker ostale etape niso izkoriščene in gredo mimo nas neopažene.

    Vodniki ne vedo ničesar o stopnji prestrezanja, ampak začnejo delati od vzpona.

    Če želite ujeti dogodek na stopnji prestrezanja, morate uporabiti samo:

    • Argument je resničen, potem bo dogodek prestrežen na poti navzdol.
    • Argument je napačen, potem bo dogodek ujet pri brbotanju.
    Primeri

    V primeru na , ,

    Procesorji so enaki kot prej, vendar tokrat na stopnji potopitve. Če želite videti prestrezanje v akciji, kliknite na element v njem

    Rokovniki bodo delovali v vrstnem redu od zgoraj navzdol: FORM → DIV → P.

    Koda JS tukaj je:

    Var elems = document.querySelectorAll("form,div,p"); // vsakemu elementu na stopnji prestrezanja priloži obravnavo za (var i = 0; i< elems.length; i++) { elems[i].addEventListener("click", highlightThis, true); }


    Nihče vam ne brani, da dodelite upravljavce za obe stopnji, takole:

    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 notranji element

    Za ogled vrstnega reda dogodkov:
    To bi moralo biti FORM → DIV → P → P → DIV → FORM. Upoštevajte, da element

    Sodeloval bo v obeh etapah.

    Rezultati
    • Ko pride do dogodka, je element, na katerem se je dogodek zgodil, označen kot event.target.
    • Dogodek se najprej premakne navzdol iz korena dokumenta v event.target, pri čemer kliče obdelovalce, posredovane prek addEventListener(…., true).
    • Dogodek se premakne iz event.target navzgor na začetek dokumenta, ob tem pa kliče obdelovalce, ki jih posreduje addEventListener(…., false).

    Vsak upravljavec bo imel dostop do lastnosti dogodka:

    • event.target je najgloblji element, kjer se je dogodek dejansko zgodil.
    • event.currentTarget (=this) – element, na katerem je trenutno sprožen samoobravnavalec (do katerega je dogodek “segel”).
    • event.eventPhase – v kateri fazi se je sprožil upravljalnik dogodkov (potop = 1, dvig = 3).

    Širjenje lahko ustavite s klicem metode event.stopPropagation(), vendar to ni priporočljivo, saj boste morda dogodek potrebovali za najbolj nepričakovane namene.