Úvod do pop-up udalostí. Pokročilá práca s objektom Event v JavaScripte Zrušenie prebublávania udalostí js

V tejto lekcii sa zoznámime s konceptom prebublávania udalostí a tiež sa pozrieme na to, ako ho možno prerušiť. Okrem toho zistíme, akými ďalšími fázami (fázami) udalosť prechádza, kým začne vznikať.

Bublina udalosti

Ak pre nejaký prvok nastane udalosť, začne „vyskakovať“, t.j. vyskytuje sa u rodiča, potom u starého rodiča atď.

Z toho vyplýva, že udalosť vygenerovanú nejakým prvkom môže byť zachytená pomocou handlera na jeho rodičovi, prarodičovi atď.

Vznik udalosti (bubliny) demonštrujeme na nasledujúcom príklade:

Smerovanie

Veľmi dôležitý text

kapitola

Nejaký text

Zvyšok textu

Napíšme si malý skript, pomocou ktorého pridáme obsluhu udalosti „click“ pre všetky prvky stránky, ako aj pre objekty dokumentu a okien.

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

Vytvorme HTML stránku a vložíme do nej vyššie uvedený HTML kód. Scenár napísaný v JavaScript, vložte pred koncovú značku tela. Potom otvorte novovytvorenú stránku vo webovom prehliadači, stlačte kláves F12 a prejdite do konzoly. Teraz kliknime ľavým tlačidlom myši na oblasť patriacu silnému prvku a uvidíme, ako sa udalosť objaví.

Ako prerušiť bublanie udalostí

Nástup udalosti (bubliny) môže byť prerušený. V tomto prípade sa táto udalosť nespustí pre vyššie (nadradené) prvky. Metóda, ktorá je navrhnutá na zastavenie šírenia udalosti (bubliny), sa nazýva stopPropagation() .

Napríklad zmeňme náš príklad vyššie tak, aby sa udalosť nezobrazovala nad telom: document.addEventListener("DOMContentLoaded", function() ( var allElements = document.getElementsByTagName("*"); for (var i=0 i

Povrchová úprava je nepochybne veľmi pohodlná a architektonicky transparentná. Nezastavujte to, pokiaľ to nie je absolútne nevyhnutné.

Získanie prvku, ktorý volal handler

Ak chcete získať prvok DOM (objekt), ktorý volal obsluhu udalosti, musíte použiť kľúč slovo toto. Dané kľúčové slovo(toto) je v obslužnom nástroji k dispozícii iba vtedy, ak sa prihlásite na odber udalosti pomocou JavaScriptu.

Napríklad zobrazme v konzole ID prvku, ktorý volal obslužný program udalosti:

Var myP = document.getElementById("myP"); myP.addEventListener("click",function())( //získať prvok DOM, ktorý volal obsluhu udalosti - toto //získať jeho id a poslať ho do konzoly console.log(this.id); ));

Na získanie aktuálneho prvku môžete použiť aj vlastnosť currentTarget (event.currentTarget).

Etapy (fázy) deja

Predtým, ako sa udalosť začne objavovať (stupeň výstupu), najskôr prejde ďalšími 2 stupňami:

  • Fáza 1 je fáza ponorenia do prvku, ktorý generoval udalosť. Tie. v tomto štádiu dochádza k pohybu zhora nadol, t.j. od okenný objekt k prvku. Táto fáza sa nazýva aj štádium odpočúvania.
  • 2. etapa je etapa dosiahnutia cieľa, t.j. prvok (objekt), ktorý generoval udalosť.

Ak vezmeme do úvahy všetky fázy, ktorými udalosť prechádza, objaví sa nasledujúci obrázok:

Upravme vyššie uvedený príklad skriptu takto:

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

Tretí parameter metód addEventListener a removeEventListener určuje štádium, v ktorom bude udalosť zachytená. Ak tento parameter je nastavená na hodnotu true , udalosť bude zachytená vo fáze ponorenia (zachytenia) udalosti. A ak je parameter nepravdivý , udalosť bude zachytená vo fáze bublania. Na spracovanie udalosti na samotnom cieli môžete použiť metódu addEventListener ako pri hodnota nepravda a s hodnotou true .

Pozor: počas fázy ponorenia (zachytenia) môžu byť udalosti zachytené iba obslužnými programami pridanými pomocou metódy addEventListener(). Obslužné nástroje pridané pomocou iných metód ( HTML atribút alebo prostredníctvom JavaScriptu pomocou vlastnosti on[event]) dokáže zachytiť udalosti iba v štádiu bublania.

Získava sa prvok, ktorý generoval udalosť

Aby ste získali cieľový prvok, t.j. prvok, ktorý udalosť vygeneroval, musí používať vlastnosť target (event.target).

Zoberme si vyššie uvedený príklad, v ktorom zmeníme obsah prvku skriptu na nasledujúci:

Document.addEventListener("DOMContentLoaded", function() ( var elementBody = document.body; elementBody.addEventListener("click",function())( console.log(this.tagName + " - prvok, ktorý volal obslužný program") ; console .log(event.currentTarget.tagName + " - prvok, ktorý volal obslužný program"); ​​console.log(event.target.tagName + " - prvok, ktorý vygeneroval udalosť"); ),false); )) ;

Ukážme si náš príklad kliknutím ľavým tlačidlom myši na oblasť patriacu silnému prvku:

Všetko to začalo používaním JavaScriptu a tried.

Mám však problém. Chcel som použiť niečo, čo sa nazýva Bubble Events, ale tiež som chcel minimalizovať závislosti, ktoré by som musel vložiť. Nechcel som sa pripojiť knižnice jQuery pre "tento malý test", stačí použiť vyskakovacie udalosti.

Pozrime sa bližšie na to, čo sú toasty, ako fungujú a na niekoľko spôsobov, ako ich realizovať.

Dobre, tak v čom je problém? Pozrime sa na jednoduchý príklad:

Povedzme, že máme zoznam tlačidiel. Zakaždým, keď kliknem na jeden z nich, mal by sa stať „aktívnym“. Po opätovnom stlačení by sa tlačidlo malo vrátiť do pôvodného stavu.

Začnime s HTML:

  • Ceruzka
  • Pero
  • guma

Mohol by som použiť štandardnú obsluhu udalostí JavaScriptu takto:

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"); }); }
Vyzerá to dobre... Ale nebude to fungovať. Autor: najmenej, nie tak, ako to očakávame.

Uzávierky vyhrávajú Pre tých, ktorí poznajú trochu funkčný JavaScript, je problém zrejmý.

Vo zvyšku to stručne vysvetlím - funkcia obsluhy je uzamknutá na premennej tlačidla. Ide však o jednu premennú a pri každej iterácii sa prepíše.

V prvej iterácii sa premenná vzťahuje na prvé tlačidlo. V ďalšom - do druhého atď. Keď však používateľ klikne na tlačidlo, cyklus sa už skončil a premenná tlačidla odkazuje na posledné tlačidlo, ktoré vždy zavolá obsluhu udalosti. Porucha.

Potrebujeme samostatný kontext pre každú funkciu:

Tlačidlá Var = document.querySelectorAll(".tlačidlo panela nástrojov"); 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])); }
Oveľa lepšie! A čo je najdôležitejšie, funguje to správne. Vytvorili sme funkciu createToolbarButtonHandle, ktorá vracia obsluhu udalosti. Potom pre každé tlačidlo pripevníme vlastný handler.

V čom je teda problém? Vyzerá to dobre a funguje. Napriek tomu môžeme náš kód vylepšiť.

Najprv vytvoríme príliš veľa handlerov. Pre každé tlačidlo vo vnútri .toolbaru vytvoríme funkciu a naviažeme ju ako obsluhu udalosti. Pre tri tlačidlá je využitie pamäte zanedbateľné.

Ale ak máme niečo takéto:

  • Foo
  • Bar
  • // ...ďalších 997 prvkov...
  • baz

potom počítač samozrejme z preplnenia nevybuchne. Naše využitie pamäte však nie je ani zďaleka ideálne. Vyčleňujeme jej obrovské množstvo, hoci sa bez nej zaobídeme. Znovu prepíšme náš kód, aby sme tú istú funkciu mohli použiť viackrát.

Namiesto odkazovania na premennú tlačidla na sledovanie toho, na ktoré tlačidlo sme klikli, môžeme použiť objekt udalosti, ktorý sa odovzdá ako prvý argument každej obsluhe udalosti.

Objekt Event obsahuje niektoré údaje o udalosti. V našom prípade nás zaujíma pole currentTarget. Z nej dostaneme odkaz na prvok, na ktorý sa kliklo:

Var toolbarButtonHandler = function(e) ( var button = e.currentTarget; if(!button.classList.contains("active")) button.classList.add("active"); inak button.classList.remove("active" );); for(var i = 0; i< buttons.length; i++) { button.addEventListener("click", toolbarButtonHandler); }
Skvelé! Nielenže sme všetko zjednodušili na jedinú funkciu, ktorá sa používa viackrát, ale tiež sme urobili náš kód čitateľnejším odstránením nepotrebnej funkcie generátora.

Stále však môžeme byť lepší.

Povedzme, že sme pridali nejaké tlačidlá do hárka po vykonaní nášho kódu. Potom by sme tiež museli pridať obslužné programy udalostí pre každú z nich. A museli by sme uložiť odkaz na tento handler a odkazy z iných miest. Nevyzerá príliš lákavo.

Možno existuje iný prístup?

Začnime tým, že pochopíme, ako udalosti fungujú a ako sa pohybujú po našom DOM.

Ako väčšina z nich funguje? Keď používateľ klikne na prvok, vygeneruje sa udalosť, ktorá o tom informuje aplikáciu. Cesta každej udalosti prebieha v troch etapách:
  • Fáza odpočúvania
  • Udalosť nastane na cieľovom prvku
  • Fáza stúpania
  • Poznámka: nie všetky udalosti prechádzajú fázou zachytenia alebo prebublávania, niektoré sa vytvárajú priamo na prvku. Ide však skôr o výnimku z pravidla.

    Udalosť sa vytvorí mimo dokumentu a potom sa postupne presúva cez hierarchiu DOM do cieľového prvku. Po dosiahnutí cieľa sa udalosť získa z prvku DOM rovnakým spôsobom.

    Tu je naša HTML šablóna:

    • Tlačidlo A
    • Tlačidlo B
    • Tlačidlo C

    Keď používateľ klikne na tlačidlo A, udalosť prebehne takto:

    Štart
    | #dokument
    | Fáza odpočúvania
    | HTML
    | BODY
    | UL
    | LI#li_1
    | Tlačidlo A< - Событие возникает для целевого элемента
    | Fáza stúpania
    | LI#li_1
    | UL
    | BODY
    | HTML
    v #dokument

    Všimnite si, že môžeme sledovať cestu, ktorú udalosť prejde, kým dosiahne svoj cieľový prvok. V našom prípade si môžeme byť istí, že pre každé stlačené tlačidlo sa udalosť vráti späť a prejde cez svojho rodiča - prvok ul. Môžeme to využiť a implementovať popup udalosti.

    Udalosti bubliny Udalosti bubliny sú tie udalosti, ktoré sú pripojené k rodičovskému prvku, ale vykonajú sa iba vtedy, ak spĺňajú určitú podmienku.

    Vezmime si náš panel nástrojov ako konkrétny príklad:

    Ul class="toolbar">

  • Ceruzka
  • Pero
  • guma

  • Teraz, keď vieme, že každé kliknutie na tlačidlo sa objaví cez prvok ul.toolbar, pripojíme k nemu našu obsluhu udalosti. Našťastie to už máme:

    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. remove("aktívne"); ));
    Teraz máme oveľa čistejší kód a dokonca sme sa zbavili slučiek! Upozorňujeme však, že e.currentTarget sme nahradili e.target . Dôvod spočíva v tom, že spracovávame udalosti na inej úrovni.

    e.target je skutočným cieľom udalosti, kde si razí cestu cez DOM a odkiaľ potom vybuchne.
    e.currentTarget – aktuálny prvok, ktorý spracováva udalosť. V našom prípade je to ul.toolbar.

    Vylepšené bublinové udalosti tento moment Každé kliknutie na každý prvok, ktorý sa objaví, spracovávame cez ul.toolbar , ale naša podmienka overenia je príliš jednoduchá. Čo by sa stalo, keby sme mali zložitejší DOM, ktorý by obsahoval ikony a prvky, na ktoré sa nedá kliknúť?

    • Ceruzka
    • Pero
    • guma

    Ojoj! Teraz, keď klikneme na li.separator alebo ikonu, pridáme k nej triedu .active. Prinajmenšom to nie je dobré. Potrebujeme spôsob, ako filtrovať udalosti, aby sme reagovali na prvok, ktorý potrebujeme.

    Vytvorme si na to malú pomocnú funkciu:

    Var delegát = funkcia (kritériá, poslucháč) ( návratová funkcia (e) ( var el = e.cieľ; do ( ak (!kritérium(el)) pokračovať; e.delegateTarget = el; poslucháč.použiť(toto, argumenty); return; ) while((el = el.parentNode)); ); );
    Náš asistent robí dve veci. Najprv iteruje každý prvok a jeho rodičov a skontroluje, či spĺňajú podmienku zadanú v parametri kritéria. Ak prvok vyhovuje, pomocník pridá do objektu udalosti pole s názvom delegátTarget, v ktorom je uložený prvok, ktorý spĺňa naše podmienky. A potom zavolá psovoda. Ak teda žiadny prvok nespĺňa podmienku, nebude zavolaný žiadny handler.

    Môžeme to použiť takto:

    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("kliknutie", delegát(buttonsFilter, buttonHandler));
    Presne to, čo lekár nariadil: jeden ovládač udalosti pripojený k jednému prvku, ktorý vykonáva všetku prácu. Ale robí to len pre prvky, ktoré potrebujeme. A perfektne reaguje na pridávanie a odstraňovanie objektov z DOM.

    Zhrnutie Stručne sme zhodnotili základy implementácie delegovania (spracovanie vyskakovacích) udalostí na čistý JavaScript. To je dobré, pretože nepotrebujeme generovať a pripájať veľa obslužných programov pre každý prvok.

    Ak by som z toho chcel vytvoriť knižnicu alebo použiť kód vo vývoji, pridal by som niekoľko vecí:

    Pomocná funkcia na kontrolu, či objekt spĺňa kritériá v jednotnejšej a funkčnejšej forme. Páči sa mi to:

    Kritériá var = ( isElement: function(e) ( return e instanceof HTMLElement; ), hasClass: function(cls) ( return function(e) ( return cycle.isElement(e) && e.classList.contains(cls); ) ) //Viac kritérií);
    Čiastočné využitie asistenta by bolo tiež užitočné:

    Var parcialDelgate = funkcia(kritéria) ( return function(handler) ( return delgate(kritéria, handler); ) );
    Pôvodný článok: Pochopenie delegovaných udalostí JavaScriptu
    (Od prekladateľa: môj prvý, posúďte prísne.)

    Šťastné kódovanie!

    Udalosti sú akcie alebo udalosti, ktoré sa vyskytnú v systéme, ktorý programujete a o ktorých vám systém povie, aby ste na ne mohli v prípade potreby nejakým spôsobom reagovať. Ak napríklad používateľ klikne na tlačidlo na webovej stránke, možno budete chcieť na túto akciu reagovať zobrazením informačného poľa. V tomto článku diskutujeme o niektorých dôležitých pojmoch týkajúcich sa udalostí a pozrieme sa na to, ako fungujú v prehliadačoch. Toto nebude vyčerpávajúca štúdia, len čo potrebuješ vedieť v tejto fáze.

    Predpoklady: Cieľ:
    Základná počítačová gramotnosť, základné pochopenie HTML a CSS, JavaScript prvé kroky.
    Pochopiť základnú teóriu udalostí, ako fungujú v prehliadačoch a ako sa udalosti môžu líšiť v rôznych programovacích prostrediach.
    Séria šťastných udalostí

    Ako už bolo spomenuté vyššie, udalosti sú akcie alebo udalosti, ktoré sa dejú v systéme, ktorý programujete – systém vytvára (alebo „vyžaruje“) signál nejakého druhu, keď nastane udalosť, a tiež poskytuje mechanizmus, pomocou ktorého je možné vykonať nejaký druh akcie. automaticky prevzaté (t. j. nejaký spustený kód), keď nastane udalosť. Napríklad na letisku, keď je pristávacia dráha voľná pre vzlet lietadla, je pilotovi oznámený signál a v dôsledku toho začnú pilotovať lietadlo.

    V prípade webu sa udalosti spúšťajú v okne prehliadača a majú tendenciu byť pripojené ku konkrétnej položke, ktorá sa v ňom nachádza – môže to byť jeden prvok, skupina prvkov, dokument HTML načítaný na aktuálnej karte alebo celé okno prehliadača. Môže nastať množstvo rôznych typov udalostí, napr.

    • Používateľ klikne myšou na určitý prvok alebo umiestni kurzor nad určitý prvok.
    • Používateľ stlačí kláves na klávesnici.
    • Používateľ zmení veľkosť alebo zatvorí okno prehliadača.
    • Odovzdáva sa formulár.
    • Video, ktoré sa prehráva, pozastavuje alebo dokončuje prehrávanie.
    • Vyskytla sa chyba.

    Z toho (a z pohľadu na referenciu udalosti MDN) môžete usúdiť, že existuje veľa udalostí, na ktoré možno reagovať.

    Každá dostupná udalosť má obslužný program udalosti , čo je blok kódu (zvyčajne funkcia JavaScript, ktorú ako programátor vytvoríte), ktorý sa spustí pri spustení udalosti. Keď je takýto blok kódu definovaný na spustenie v reakcii na spustenie udalosti, hovoríme, že registrujeme obsluhu udalosti . Všimnite si, že obslužné programy udalostí sa niekedy nazývajú poslucháči udalostí – pre naše účely sú do značnej miery zameniteľné, aj keď prísne vzaté, spolupracujú. Poslucháč počúva, či sa udalosť deje, a handler je kód, ktorý je spustený v reakcii na udalosť.

    Poznámka: Webové udalosti nie sú súčasťou základného jazyka JavaScript – sú definované ako súčasť rozhraní API zabudovaných v prehliadači.

    Jednoduchý príklad

    Pozrime sa na jednoduchý príklad, aby sme vysvetlili, čo tu máme na mysli. Udalosti a obslužné programy udalostí ste už videli v mnohých príkladoch v tomto kurze, ale zopakujme si to, aby sme upevnili naše znalosti. V nasledujúcom príklade máme single , po stlačení ktorej sa pozadie zmení na náhodnú farbu:

    Zmeniť farbu

    Tlačidlo ( okraj: 10px );

    JavaScript vyzerá takto:

    Const btn = document.querySelector("tlačidlo"); function 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 tomto kóde ukladáme odkaz na tlačidlo vnútri konštanty s názvom btn pomocou funkcie Document.querySelector(). Definujeme tiež funkciu, ktorá vracia náhodné číslo. Treťou časťou kódu je obsluha udalosti. Konštanta btn ukazuje na prvok a tento typ objektu má množstvo udalostí, ktoré sa na ňom môžu spustiť, a preto sú k dispozícii obslužné programy udalostí. Sledujeme spustenie udalosti kliknutia nastavením vlastnosti obsluhy udalosti onclick na rovnakú anonymnú funkciu obsahujúcu kód, ktorý generuje náhodnú farbu RGB a nastavuje jej rovnakú farbu.

    Tento kód sa spustí vždy, keď sa na prvok spustí udalosť kliknutia, teda vždy, keď naň používateľ klikne.

    Príklad výstupu je nasledujúci:

    Nie sú to len webové stránky

    Ďalšia vec, ktorú v tomto bode stojí za zmienku, je, že udalosti nie sú jedinečné pre JavaScript – väčšina programovacích jazykov má nejaký model udalostí a spôsob, akým model funguje, sa často líši od spôsobu JavaScriptu. V skutočnosti model udalostí v JavaScripte pre webové stránky sa líši od modelu udalostí pre JavaScript, pretože sa používa v iných prostrediach.

    Inline obslužné nástroje udalostí – nepoužívajte ich

    Vo svojom kóde môžete vidieť aj takýto vzor:

    Funkcia Stlačte ma bgChange() ( const rndCol = "rgb(" + random(255) + "," + random(255) + "," + random(255) + ")"; document.body.style.backgroundColor = rndCol ;)

    Najskorší spôsob registrácie obslužných nástrojov udalostí, ktorý sa našiel na webe, zahŕňal atribúty HTML obslužného programu udalosti (alebo vložené obslužné nástroje udalostí ), ako je ten, ktorý je uvedený vyššie – hodnota atribútu je doslova kód JavaScript, ktorý chcete spustiť, keď nastane udalosť. Vyššie uvedený príklad vyvolá funkciu definovanú vo vnútri prvku na tej istej stránke, ale JavaScript môžete vložiť aj priamo do atribútu, napríklad:

    Stlačte ma

    Môžete nájsť ekvivalenty atribútov HTML pre mnohé vlastnosti obsluhy udalostí; nemali by ste ich však používať – považujú sa za zlý postup. Môže sa zdať jednoduché použiť atribút obsluhy udalosti, ak robíte niečo naozaj rýchlo, ale veľmi rýchlo sa stanú neovládateľnými a neúčinnými.

    Na začiatok nie je dobrý nápad zamieňať si kód HTML a JavaScript, pretože je ťažké ho analyzovať – lepšie je ponechať celý JavaScript na jednom mieste; ak je v samostatnom súbore, môžete ho použiť na viacero dokumentov HTML.

    Dokonca ani v jednom súbore nie sú inline obslužné programy udalostí dobrý nápad. Jedno tlačidlo je v poriadku, ale čo keby ste mali 100 tlačidiel? Do súboru by ste museli pridať 100 atribútov; veľmi rýchlo by sa to zmenilo na údržbu. S JavaScriptom by ste mohli jednoducho nočnou morou pridať funkciu obsluhy udalostí ku všetkým tlačidlám na stránke bez ohľadu na to, koľko ich bolo, pomocou niečoho ako toto:

    Const buttons = document.querySelectorAll("tlačidlo"); pre (nech i = 0; i< buttons.length; i++) { buttons[i].onclick = bgChange; } buttons.forEach(function(button) { button.onclick = bgChange; });

    Poznámka: Oddelenie logiky programovania od obsahu tiež robí vašu stránku priateľskejšiu pre vyhľadávače.

    addEventListener() a removeEventListener()

    Najnovší typ mechanizmu udalostí je definovaný v špecifikácii udalostí úrovne 2 modelu dokumentu (DOM), ktorá poskytuje prehliadačom novú funkciu - addEventListener() . Funguje to podobne ako vlastnosti obsluhy udalosti, ale syntax je zjavne odlišná. Náš náhodný farebný príklad by sme mohli prepísať takto:

    Const btn = document.querySelector("tlačidlo"); funkcia bgChange() ( const rndCol = "rgb(" + random(255) + "," + random(255) + "," + random(255) + ")"; document.body.style.backgroundColor = rndCol; ) btn.addEventListener("kliknutie", bgChange);

    Vo vnútri funkcie addEventListener() zadávame dva parametre – názov udalosti, pre ktorú chceme tento handler zaregistrovať, a kód, ktorý obsahuje funkciu handlera, ktorú chceme spustiť ako odpoveď naň. Všimnite si, že je úplne vhodné vložiť celý kód do funkcie addEventListener() v anonymnej funkcii, ako je táto:

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

    Tento mechanizmus má určité výhody oproti starším mechanizmom, o ktorých sme hovorili vyššie. Na začiatok je tu náprotivná funkcia removeEventListener() , ktorá odstráni predtým pridaný poslucháč. Napríklad by sa tým odstránil poslucháč nastavený v prvom bloku kódu v tejto sekcii:

    Btn.removeEventListener("click", bgChange);

    To nie je dôležité pre jednoduché, malé programy, ale pre väčšie a zložitejšie programy to môže zvýšiť efektivitu čistenia starých nepoužívaných obslužných programov udalostí. Navyše vám to napríklad umožňuje, aby to isté tlačidlo vykonávalo rôzne akcie za rôznych okolností – všetko, čo musíte urobiť, je pridať alebo odstrániť obslužné programy udalostí podľa potreby.

    Po druhé, môžete tiež zaregistrovať viacero obslužných programov pre toho istého poslucháča. Nasledujúce dva obslužné nástroje by sa nepoužili:

    MyElement.onclick = functionA; myElement.onclick = functionB;

    Druhý riadok prepíše hodnotu onclick nastavenú prvým riadkom. Toto by však fungovalo:

    MyElement.addEventListener("kliknutie", funkciaA); myElement.addEventListener("kliknutie", funkciaB);

    Obe funkcie by sa teraz spustili po kliknutí na prvok.

    Okrem toho je s týmto mechanizmom udalostí k dispozícii množstvo ďalších výkonných funkcií a možností. Tieto sú trochu mimo rozsah tohto článku, ale ak si ich chcete prečítať, pozrite si referenčné stránky addEventListener() a removeEventListener().

    Aký mechanizmus by som mal použiť?

    Z týchto troch mechanizmov by ste rozhodne nemali používať atribúty obsluhy udalostí HTML – tieto sú zastarané a zlé, ako je uvedené vyššie.

    Ďalšie dva sú relatívne zameniteľné, aspoň pre jednoduché použitie:

    • Vlastnosti obsluhy udalostí majú menší výkon a možnosti, ale lepšiu kompatibilitu medzi prehliadačmi (podporované už od internet Explorer 8). Pravdepodobne by ste s nimi mali začať, keď sa učíte.
    • Udalosti DOM úrovne 2 (addEventListener() atď.) sú výkonnejšie, ale môžu byť aj zložitejšie a sú menej podporované (podporované už od Internet Explorera 9). Mali by ste s nimi tiež experimentovať a snažiť sa ich používať tam, kde je to možné.

    Hlavné výhody tretieho mechanizmu spočívajú v tom, že v prípade potreby môžete odstrániť kód obsluhy udalosti pomocou removeEventListener() a v prípade potreby môžete k prvkom pridať viacero poslucháčov rovnakého typu. Môžete napríklad volať addEventListener("click", function() ( ... )) na prvok viackrát, pričom v druhom argumente sú špecifikované rôzne funkcie. Pri vlastnostiach obsluhy udalosti to nie je možné, pretože akékoľvek následné pokusy o nastavenie vlastnosti prepíšu predchádzajúce, napr.:

    Element.onclick = function1; element.onclick = function2; atď.

    Poznámka: Ak ste vyzvaní, aby ste pri svojej práci podporovali prehliadače staršie ako Internet Explorer 8, môžete sa stretnúť s ťažkosťami, pretože tieto staré prehliadače používajú iné modely udalostí ako novšie prehliadače. Ale nebojte sa, väčšina knižníc JavaScript (napríklad jQuery) má vstavané funkcie, ktoré abstrahujú rozdiely medzi rôznymi prehliadačmi. Netrápte sa tým príliš v tejto fáze vašej cesty učenia.

    Ďalšie koncepty udalostí

    V tejto časti stručne popíšeme niektoré pokročilé koncepty, ktoré sú relevantné pre udalosti. V tomto bode nie je dôležité plne porozumieť týmto pojmom, ale môžu slúžiť na vysvetlenie niektorých vzorcov kódu, s ktorými sa z času na čas pravdepodobne stretnete.

    Objekty udalostí

    Niekedy vo funkcii obsluhy udalosti môžete vidieť parameter zadaný s názvom, ako je event , evt alebo jednoducho e . Toto sa nazýva objekt udalosti a automaticky sa odovzdá obsluhe udalostí, aby poskytovalo ďalšie funkcie a informácie. Napríklad znova mierne prepíšme náš náhodný farebný príklad:

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

    Tu môžete vidieť, že do funkcie zahrnieme objekt udalosti, e , a do funkcie nastavíme štýl farby pozadia na e.target – čo je samotné tlačidlo. Vlastnosť target objektu udalosti je vždy odkaz na prvok, na ktorom sa udalosť práve vyskytla. V tomto príklade teda nastavujeme náhodnú farbu pozadia na tlačidle, nie na stránke.

    Poznámka: Pre objekt udalosti môžete použiť ľubovoľný názov – stačí si vybrať názov, ktorý potom môžete použiť na odkazovanie vo funkcii obsluhy udalosti. e/evt/event sú najčastejšie používané vývojármi, pretože sú krátke a ľahko zapamätateľné. Vždy je dobré byť konzistentný – so sebou samým a s ostatnými, ak je to možné.

    e.target je neuveriteľne užitočný, keď chcete nastaviť rovnakú obsluhu udalosti na viacerých prvkoch a urobiť niečo so všetkými, keď sa na nich vyskytne udalosť. Môžete mať napríklad sadu 16 dlaždíc, ktoré zmiznú, keď na ne kliknete. Je užitočné mať vždy možnosť jednoducho nastaviť, aby vec zmizla ako e.target , namiesto toho, aby ste ju museli vyberať nejakým zložitejším spôsobom. V nasledujúcom príklade (pozri užitočný-eventtarget.html pre úplný zdrojový kód; môžete si ho pozrieť aj naživo tu) vytvoríme 16 prvkov pomocou JavaScriptu. Potom ich všetky vyberieme pomocou document.querySelectorAll() , potom prejdeme každý z nich a ku každému pridáme obslužný program onclick, vďaka ktorému sa na každý z nich po kliknutí použije náhodná farba:

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

    Výstup je nasledujúci (skúste naň kliknúť - bavte sa):

    Skrytý príklad Užitočný príklad cieľa udalosti div ( výška: 100 pixelov; šírka: 25 %; float: left; ) pre (nech i = 1; i
  • Ceruzka
  • Pero
  • guma

  • Teraz, keď vieme, že každé kliknutie na tlačidlo sa objaví cez prvok ul.toolbar, pripojíme k nemu našu obsluhu udalosti. Našťastie to už máme:

    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. remove("aktívne"); ));
    Teraz máme oveľa čistejší kód a dokonca sme sa zbavili slučiek! Upozorňujeme však, že e.currentTarget sme nahradili e.target . Dôvod spočíva v tom, že spracovávame udalosti na inej úrovni.

    e.target je skutočným cieľom udalosti, kde si razí cestu cez DOM a odkiaľ potom vybuchne.
    e.currentTarget – aktuálny prvok, ktorý spracováva udalosť. V našom prípade je to ul.toolbar.

    Vylepšené vyskakovacie udalosti V súčasnosti spracovávame každé kliknutie na každý prvok, ktorý sa objaví cez ul.toolbar , ale naša podmienka overenia je príliš jednoduchá. Čo by sa stalo, keby sme mali zložitejší DOM, ktorý by obsahoval ikony a prvky, na ktoré sa nedá kliknúť?

    • Ceruzka
    • Pero
    • guma

    Ojoj! Teraz, keď klikneme na li.separator alebo ikonu, pridáme k nej triedu .active. Prinajmenšom to nie je dobré. Potrebujeme spôsob, ako filtrovať udalosti, aby sme reagovali na prvok, ktorý potrebujeme.

    Vytvorme si na to malú pomocnú funkciu:

    Var delegát = funkcia (kritériá, poslucháč) ( návratová funkcia (e) ( var el = e.cieľ; do ( ak (!kritérium(el)) pokračovať; e.delegateTarget = el; poslucháč.použiť(toto, argumenty); return; ) while((el = el.parentNode)); ); );
    Náš asistent robí dve veci. Najprv iteruje každý prvok a jeho rodičov a skontroluje, či spĺňajú podmienku zadanú v parametri kritéria. Ak prvok vyhovuje, pomocník pridá do objektu udalosti pole s názvom delegátTarget, v ktorom je uložený prvok, ktorý spĺňa naše podmienky. A potom zavolá psovoda. Ak teda žiadny prvok nespĺňa podmienku, nebude zavolaný žiadny handler.

    Môžeme to použiť takto:

    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("kliknutie", delegát(buttonsFilter, buttonHandler));
    Presne to, čo lekár nariadil: jeden ovládač udalosti pripojený k jednému prvku, ktorý vykonáva všetku prácu. Ale robí to len pre prvky, ktoré potrebujeme. A perfektne reaguje na pridávanie a odstraňovanie objektov z DOM.

    Zhrnutie Stručne sme sa pozreli na základy implementácie delegovania (spracovanie vyskakovacích) udalostí v čistom JavaScripte. To je dobré, pretože nepotrebujeme generovať a pripájať veľa obslužných programov pre každý prvok.

    Ak by som z toho chcel vytvoriť knižnicu alebo použiť kód vo vývoji, pridal by som niekoľko vecí:

    Pomocná funkcia na kontrolu, či objekt spĺňa kritériá v jednotnejšej a funkčnejšej forme. Páči sa mi to:

    Kritériá var = ( isElement: function(e) ( return e instanceof HTMLElement; ), hasClass: function(cls) ( return function(e) ( return cycle.isElement(e) && e.classList.contains(cls); ) ) //Viac kritérií);
    Čiastočné využitie asistenta by bolo tiež užitočné:

    Var parcialDelgate = funkcia(kritéria) ( return function(handler) ( return delgate(kritéria, handler); ) );
    Pôvodný článok: Pochopenie delegovaných udalostí JavaScriptu
    (Od prekladateľa: môj prvý, posúďte prísne.)

    Šťastné kódovanie!

    Ahoj! V tejto lekcii chcem hovoriť o takom dôležitom koncepte, akým je sledovanie a zachytávanie udalostí. Bublinkovanie je jav, pri ktorom ak kliknete na podradený prvok, udalosť sa rozšíri na jeho rodiča.

    Môže to byť veľmi užitočné pri spracovávaní veľkých vnorených zoznamov alebo tabuliek; aby ste každému prvku nepriradili obsluhu udalosti, môžete rodičovskému prvku priradiť jednu obsluhu a udalosť sa už rozšíri na všetky vnorené prvky v nadradenom prvku. Pozrime sa na príklad.

    Tento obslužný nástroj sa spustí, ak kliknete na podznačku alebo:

    Kliknite na EM, bude fungovať handler na DIV

    Ako vidíte, keď kliknete na vnorený prvok em, spustí sa obslužný program prvku div. Prečo sa to deje? Čítajte ďalej a dozviete sa.

    Výstup

    Takže základný princíp stúpania:

    Keď dôjde k udalosti akéhokoľvek druhu, nezáleží na tom, či sa klikne myšou na prvok, udalosť sa najskôr spustí na nadradenom prvku a potom sa pozdĺž reťazca rozšíri na všetky vnorené prvky.

    Predpokladajme napríklad, že existujú 3 vnorené prvky FORM > DIV > P, s obslužnou rutinou udalosti na každom z nich:

    telo * ( okraj: 10px; orámovanie: 1px plná modrá; ) FORM DIV

    Bublinkovanie zaisťuje kliknutie na vnútorný prvok

    Najprv zavolá obsluhu kliknutia (ak existuje, samozrejme).

    Tento proces sa nazýva vzostup, pretože sa zdá, že udalosti „vznášajú“ z vnútorného prvku nahor cez svojich rodičov, rovnako ako vzduchová bublina pláva vo vode, takže môžete nájsť aj definíciu bublania, no, je to len z angličtiny slovo bublať - vznášať sa.

    Prístup k cieľovému prvku event.target

    Aby sme zistili, na ktorom prvku sme zachytili tú či onú udalosť, existuje metóda event.target. (prečítajte si o objekte udalosti).

    • event.target je skutočný zdrojový prvok, na ktorom sa udalosť vyskytla.
    • toto je vždy aktuálny prvok, ktorý bublanie dosiahlo a na ňom práve beží handler.

    Napríklad, ak máte nainštalovaný iba jeden obslužný program form.onclick, potom „zachytí“ všetky kliknutia vo formulári. Navyše, bez ohľadu na to, kde je kliknutie vo vnútri, stále vyskočí na prvok, na ktorom bude handler pracovať.

    kde:

    • toto (=event.currentTarget) bude vždy samotný formulár, pretože na ňom bol spustený handler.
    • event.target bude obsahovať odkaz na konkrétny prvok vo formulári, najviac vnorený prvok, na ktorý sa kliklo.

    V zásade sa to môže zhodovať s event.target, ak sa na formulár klikne a vo formulári už nie sú žiadne prvky.

    Zastavenie stúpania

    Prebublávanie udalosti zvyčajne smeruje priamo nahor a dosiahne objekt koreňového okna.

    Ale je možné zastaviť stúpanie na nejakom medzičlánku.

    Ak chcete zastaviť šírenie, musíte zavolať metódu event.stopPropagation().

    Pozrime sa na príklad: keď sa klikne na tlačidlo, obslužný program body.onclick nebude fungovať:

    Klikni na mňa

    Ak má prvok nainštalovaných niekoľko obslužných programov pre rovnakú udalosť, potom aj keď prestane bublanie, vykonajú sa všetky.

    StopPropagation teda zabráni ďalšiemu šíreniu udalosti, ale všetky obslužné programy budú pracovať na prvku, ale nie na nasledujúcom prvku.

    Ak chcete zastaviť spracovanie na aktuálnom prvku, prehliadače podporujú metódu event.stopImmediatePropagation(). Táto metóda nielen zabráni prebublávaniu, ale tiež zastaví spracovanie udalostí na aktuálnom prvku.

    Potápať sa

    V štandarde je okrem „výstupu“ udalostí aj „potápanie“.

    Potápanie, na rozdiel od výstupu, je menej žiadané, ale stále bude užitočné o ňom vedieť.

    Udalosť má teda 3 fázy:

  • Udalosť prichádza zhora nadol. Táto fáza sa nazýva „štádium odpočúvania“.
  • Udalosť dosiahla špecifický prvok. Toto je „cieľová fáza“.
  • Po všetkom sa udalosť začína vynárať. Toto je „stupeň výstupu“.
  • V norme je to demonštrované takto:

    Keď teda kliknete na TD, udalosť sa presunie po reťazci rodičov, najprv nadol k prvku („potopí sa“) a potom nahor („vyskočí“), pričom sa počas cesty použijú príslušné ovládače.

    Vyššie som písal len o stúpaní, pretože ostatné etapy nie sú využívané a prechádzajú nami bez povšimnutia.

    Psovodi nevedia nič o záchytnej fáze, ale začínajú pracovať od stúpania.

    A aby ste zachytili udalosť vo fáze odpočúvania, stačí použiť:

    • Argument je pravdivý, potom bude udalosť zachytená na ceste dole.
    • Argument je nepravdivý, potom sa udalosť zachytí pri prebublávaní.
    Príklady

    V príklade na , ,

    Procesory sú rovnaké ako predtým, ale tentoraz vo fáze ponorenia. Ak chcete vidieť odpočúvanie v akcii, kliknite na prvok v ňom

    Manipulátory budú pracovať v poradí zhora nadol: FORM → DIV → P.

    Tu je kód JS:

    Var elems = document.querySelectorAll("form,div,p"); // pripojí obsluhu ku každému prvku vo fáze zachytávania pre (var i = 0; i< elems.length; i++) { elems[i].addEventListener("click", highlightThis, true); }


    Nikto vám nebráni prideliť obslužné osoby pre obe fázy, ako je tento:

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

    Kliknite na vnútorný prvok

    Ak chcete zobraziť poradie udalostí:
    Malo by to byť FORM → DIV → P → P → DIV → FORM. Všimnite si, že prvok

    Zúčastní sa oboch etáp.

    Výsledky
    • Keď nastane udalosť, prvok, na ktorom sa udalosť vyskytla, je označený ako event.target.
    • Udalosť sa najprv presunie nadol z koreňového adresára dokumentu do event.target, pričom po ceste zavolá obslužné programy, ktoré sa dodajú cez addEventListener(…., true).
    • Udalosť sa presunie z event.target na začiatok dokumentu, pričom volá handlery dodávané cez addEventListener(…., false).

    Každý obslužný program bude mať prístup k vlastnostiam udalosti:

    • event.target je najhlbší prvok, kde k udalosti skutočne došlo.
    • event.currentTarget (=toto) – prvok, na ktorom je self-handler aktuálne spustený (na ktorý udalosť „dosiahla“).
    • event.eventPhase – v akej fáze bola spustená obsluha udalosti (ponor = 1, vzostup = 3).

    Šírenie možno zastaviť volaním metódy event.stopPropagation(), ale neodporúča sa to, pretože udalosť možno budete potrebovať na najneočakávanejšie účely.