Evenimente JavaScript de la Ground Up

Aproape tot ceea ce faci în JavaScript ar trebui să înceapă atunci când se întâmplă ceva: utilizatorul face clic pe un buton, se deplasează peste un meniu, apasă o cheie, primești ideea. Este destul de simplu să faci cu biblioteci cum ar fi jQuery, dar știi cum să conduci evenimente în JavaScript primar? Astăzi, o să vă învăț exact asta!


Bine ați venit la evenimentele JavaScript

Manipularea evenimentelor JavaScript nu este știință pentru rachete. Desigur, există diferențe în browser (ce te-ai aștepta?), Dar odată ce ai să te agiți și să-ți construiești propriile funcții de ajutor chiar și pe terenul de joc, vei fi bucuros că o știi. Chiar dacă intenționați să folosiți o bibliotecă pentru astfel de lucruri, este bine să știți ce se întâmplă sub suprafață. Începem.


Nivelul 0 Manipularea evenimentelor

Manipularea cea mai de bază a evenimentului în JavaScript este manipularea evenimentelor la nivelul 0. Este destul de ușor: trebuie doar să atribuiți funcția proprietății evenimentului pe element. Observa:

 var element = document.getElementById ('myElement'); element.onclick = function () alertă ("funcția dvs. aici"); ;

Odată ce am elementul, am setat onclick proprietate egală cu o funcție. Acum, când element se face clic, funcția va fi rulată și vom vedea o casetă de alertă.
Dar cum am știut să o folosesc onclick? Puteți obține o listă de evenimente disponibile la Wikipedia. Frumusețea despre metoda de nivel 0 este că este acceptată pe toate browserele utilizate astăzi. Dezavantajul este că puteți înregistra fiecare eveniment o dată cu fiecare element. Deci, aceasta va provoca o singură alertă:

 element.onclick = funcția () alert ('funcția 1'); ; element.onclick = funcția () alertă ("suprascriu funcția 1");

Numai a doua funcție se va executa atunci când elementul este apăsat, deoarece am reasignat proprietatea onclick. Pentru a elimina un handler de evenimente, putem să-l setăm la nul.

 element.onclick = null;

Deși oferă doar funcționalități de bază, suportul consistent din toate browserele face ca manipularea evenimentului de nivel 0 să fie o opțiune valabilă pentru proiecte foarte simple.


Full Screencast



Obiectul evenimentului și acesta

Acum, că încălziți evenimentele JavaScript, să discutăm două aspecte importante înainte de a trece la tehnici mai bune: obiectul evenimentului și acest cuvinte cheie. Când un eveniment este executat, există o mulțime de informații despre evenimentul pe care ați putea dori să îl cunoașteți: ce cheie a fost apăsată? la ce element a fost făcut clic? a făcut clic cu butonul din stânga, din dreapta sau din mijloc? Toate aceste date și mai mult sunt stocate într-un obiect de eveniment. Pentru toate browserele, cu excepția Internet Explorer, puteți ajunge la acest obiect prin trecerea acestuia ca parametru al funcției de manipulare. În IE, îl puteți obține de la variabila globală window.event. Nu este greu să rezolvi această diferență.

 funcția myFunction (evt) evt = evt || window.event; / * ... * / element.onclick = funcția mea;

myFunction ia parametrul de eveniment pentru toate browserele bune și îl redistribuim window.event dacă EVT nu există. Vom analiza câteva din proprietățile obiectului evenimentului un pic mai târziu.

acest cheia este importantă în cadrul funcțiilor de gestionare a evenimentelor; se referă la elementul care a primit evenimentul.

 element.onclick = funcția () this.style.backgroundColor = 'roșu'; // aceeași ca element.style.backgroundColor = 'roșu'; 

Din păcate, în Internet Explorer, acest nu se referă la elementul acționat; se referă la obiectul ferestrei. Asta e inutil, dar ne vom uita la o modalitate de a remedia asta putin.


Nivelul 2 Manipularea evenimentelor

Manipularea evenimentelor la nivelul 2 este specificația W3C pentru evenimentele DOM. Este destul de simplu, de fapt.

 element.addEventListener ('mouseover', myFunction, false);

Se numește metoda addEventListener. Primul parametru este tipul de eveniment pe care dorim să îl ascultăm. De obicei, este același nume cu evenimentele de nivel 0, fără prefixul "pe". Al doilea parametru este fie un nume de funcție, fie o funcție în sine. Parametrul final determină dacă captem sau nu; o vom discuta într-o clipă.
Una dintre marile beneficii ale utilizării addEventListener este că acum putem aloca mai multe evenimente pentru un eveniment unic pe un singur element:

 element.addEventListener ('dblclick', logSuccessToConsole, false); element.addEventListener ('dblclick', funcția () console.log ('această funcție nu suprimă prima');, false);

Pentru a elimina aceste dispozitive, utilizați funcția removeEventListener. Deci, pentru a elimina funcția pe care am adăugat-o mai sus, facem acest lucru:

 element.removeEventListener ('dblclick', logSuccessToConsole, false);

Captură și Bubbling

Parametrul final din addEventListner și removeEventListener este un boolean care definește dacă declanșăm evenimentul în stadiul de captură sau de bubble. Iată ce înseamnă:
Când faceți clic pe un element, faceți clic, de asemenea, pe fiecare element al strămoșilor săi.

  
Salvați locul de muncă

Dacă dau clic pe # salva deschidere, De asemenea, am făcut clic # Bara de instrumente div, div # înveliș, și corp. Deci, dacă oricare dintre aceste elemente au ascultători de evenimente care ascultă pentru clicuri, se vor apela funcțiile lor respective. Dar ce ordine ar trebui să fie chemată? Asta decide ultimul parametru. În spec. W3C, evenimentul nostru de clic va începe la corp și deplasați în jos lanțul până când ajunge la # salva deschidere; aceasta este etapa de capturare. Apoi, merge de la # salva deschidere înapoi la corp; asta e stadiul de bubble. Acest lucru este ușor de reținut, deoarece bulele plutesc în sus. Nu toate evenimentele bubble; că diagrama Wikipedia vă va spune care dintre ele fac și care nu.

Deci, dacă parametrul de captură este setat la Adevărat, evenimentul va fi declanșat pe drum; dacă este setat fals, acesta va fi declanșat pe drum.

S-ar putea să fi observat că, până acum, toate exemplele mele au stabilit captarea la fals, astfel că evenimentul este declanșat în stadiul de bubble. Acest lucru se datorează faptului că Internet Explorer nu are o fază de captare. În IE, evenimentele doar bubble.


Modelul evenimentului Internet Explorer

IE are propriul mod propriu de a lucra cu evenimente. Folosește attachEvent.

 element.attachEvent ("onclick", runThisFunction);

Din moment ce evenimentele IE sunt doar bubble, nu aveți nevoie de a treia variabilă. Primele două sunt aceleași ca și cu addEventListener, cu mare excepție că IE necesită prefixul "pe" pentru tipul evenimentului. Desigur, puteți atribui mai multe evenimente de același tip unui element individual cu acest model. Pentru a elimina evenimentele, utilizați detachEvent.

 element.detachEvent ("onclick", runThisFunction);

Momentan Înapoi la Bubbling

Ce-ar fi dacă elementele voastre nu vor ca părinții să afle despre evenimentele lor? Nu este greu să te ascunzi. În IE, utilizați cancelBubble proprietatea asupra obiectului evenimentului care trece la funcția apelată. Pentru restul, puteți folosi stopPropogation , de asemenea, pe obiectul evenimentului.

 e.cancelBubble = true; dacă (e.stopPropagation) e.stopPropagation (); 

stopPropogation metoda va opri, de asemenea, evenimentele din piesele lor în timpul etapei de capturare.


Câteva proprietăți ale obiectului evenimentului

Aș fi dispus să pariez că majoritatea proprietăților din obiectul evenimentului vor rămâne neutilizate, dar sunt câteva dintre cele selectate pe care le-ați găsit de neprețuit. Să ne uităm la cei câțiva.


ţintă

ţintă proprietatea este cel mai adânc element pe care a fost făcut clic. În imaginea de mai sus, puteți vedea că am făcut clic Butonul h1 #. În IE, această proprietate este numită srcElement; pentru a ajunge la această proprietate, faceți ceva de genul:

 var țintă = e.target || e.srcElement;

currentTarget

currentTarget proprietatea este elementul care are evenimentul chiar acum. În acea captură de ecran, currentTarget este div # înveliș. Aceasta înseamnă că am făcut clic Butonul h1 #, dar obiectul evenimentului a fost înregistrat în consola în funcția numită de div # învelișascultător al evenimentului.

Dar asta vă va arunca pentru o buclă: IE nu are o proprietate curentăTarget sau ceva asemănător. Reamintind faptul că IE nici nu lasă acest egal cu elementul care declanșează evenimentul, acest lucru înseamnă că nu avem nici o modalitate de a obține elementul care a declanșat evenimentul atunci când acesta este bubbling în sus (ceea ce înseamnă că un descendent al elementului a fost click). Confuz? Poate un exemplu va ajuta: dacă, în Internet Explorer, avem acest HTML ...

 
Buton

... și acest handler de evenimente ...

 var par = document.getElementById ("părinte"); parent.attachEvent ("onclick", doSomething);

... atunci când faceți clic pe Durata # copil iar evenimentul se bulează până la div # părinte, nu avem nici o cale din interiorul funcției Fă ceva pentru a ajunge la element (în acest caz, div # părinte) evenimentul a fost declanșat la.

Alții

Există alte proprietăți ale obiectului evenimentului pe care le veți găsi utile, în funcție de caz. La un eveniment de tastatură (tasta, tastatura, apăsarea tastei), veți fi cod cheie si charCode. Veți putea afla dacă utilizatorul a ținut apăsată tasta alt, shift sau ctrl (cmd) în timp ce apăsați / dă clic pe. Explorați obiectele evenimentului de evenimente diferite și vedeți cu ce aveți de lucrat!


Fixarea evenimentelor

Am întâlnit două probleme principale în studierea evenimentelor de până acum.

  • IE utilizează un model diferit de celelalte browsere.
  • IE nu are nici o modalitate de a accesa obiectul principal al evenimentului; îi lipsește currentTarget proprietate, și acest Obiectul trimite referințe la obiectul ferestrei.

Pentru a rezolva aceste probleme, să construim două funcții cu suport pentru cross-browser, unul pentru a conecta evenimente și unul pentru a le elimina.

Vom începe cu asta addEvent; iată primul rând:

 var addEvent = funcție (element, tip, fn) if (element.attachEvent) element.attachEvent (tip "on" +, fn);  altceva element.addEventListener (type, fn, false); 

Am atribuit o funcție anonimă variabilei addEvent pentru motivele pe care le veți vedea într-un minut. Tot ce trebuie să facem este să verificăm dacă elementul are attachEvent metodă. Dacă da, suntem în IE și vom folosi acea metodă. Dacă nu, putem folosi addEventListener.

Cu toate acestea, acest lucru nu stabilește faptul că nu avem nicio modalitate de a accesa elementul părinte al evenimentului în IE. Pentru a face acest lucru, vom face funcția un atribut al elementului; în acest fel, este percepută ca o metodă a elementului și acest va fi egal cu elementul. Da, știu, strălucitoare, nu-i așa? Ei bine, eu nu pot lua nici un credit: această idee provine dintr-un post blog de John Resig.

 var addEvent = funcție (element, tip, fn) if (element.attachEvent) element ['e' + tip + fn] = fn; elementul [type + fn] = funcția () element ['e' + type + fn] (window.event); element.attachEvent (tip "on" +, element [type + fn]);  altceva element.addEventListener (type, fn, false); 

Prima linie extra (element ['e' + tip + fn] = fn;) face funcția o metodă a elementului, astfel încât acest va egala elementul. A doua linie este o funcție care execută metoda, trecând în obiectul window.event. Acest lucru vă salvează pasul suplimentar de verificare a parametrului obiect eveniment în cadrul funcției. În cele din urmă, observați că am modificat parametrul funcției din attachEvent metoda de a Element [tipul + fn].

Asta ne rezolvă cele două probleme. Acum ne putem folosi addEvent în toate browserele cu o experiență similară posibilă. Dar există o mică optimizare pe care am vrea să o facem.

Observați că de fiecare dată addEvent funcția se numește, verifică pentru attachEvent metodă. Nu există niciun motiv pentru care ar trebui să verificăm acest lucru de mai multe ori, indiferent de numărul de evenimente pe care vrem să le înregistrăm. Putem folosi un truc minunat care ne va permite să re-scriem addEvent.

 var addEvent = funcția (el, type, fn) if (el.attachEvent) addEvent = funcția (el, type, fn) el ['e' + type + fn] = fn; el [type + fn] = funcția () el ['e' + tip + fn] (window.event); ; el.attachEvent (tipul "on" +, el [type + fn]);  altfel addEvent = funcția (el, type, fn) el.addEventListener (type, fn, false);  addEvent (el, tip, fn); 

Acum, dacă addEvent se găsește metoda, vom re-scrie addEvent pentru a include doar componentele IE; dacă nu, vom include doar părțile bune ale browserului.
Al nostru removeEvent funcția va fi foarte asemănătoare:

 var removeEvent = funcție (element, tip, fn) if (element.detachEvent) removeEvent = funcție (element, tip, fn) element.detachEvent (tip "on" + el [type + fn]); element [tip + fn] = null;  altceva removeEvent = funcție (element, tip, fn) element.removeEventListener (type, fn, false);  removeEvent (element, tip, fn); 

Asta e pentru funcțiile evenimentului încrucișat în browsere. Există un lucru care nu-mi place despre ei, totuși: funcțiile nu sunt metode ale elementelor; în schimb, elementul este un parametru. Știu că e doar o chestiune de stil, dar îmi place

 btn.addEvent ("faceți clic", doThis);

mai bun decât

 addEvent (btn, 'click', doThis);

Am putea face acest lucru prin împachetarea funcțiilor noastre în acest sens:

 var E = Element.prototip; E.addEvent = funcția (tip, fn) addEvent (acest tip, fn);  E.removeEvent = funcție (tip, fn) removeEvent (acest tip, fn); 

Acest lucru va funcționa în toate browserele moderne, precum și IE8; IE7 și IE6 sufoca pe Element. Depinde de publicul tău; ia-l sau pleaca!


Evenimentul Delegatie

Acum că știți totul despre evenimentele JavaScript, nu vă grăbiți și completați următorul proiect cu ascultători de evenimente. Dacă aveți multe elemente care răspund la același tip de eveniment (de exemplu, faceți clic pe), este mai înțelept să profitați de bule. Puteți adăuga un ascultător de eveniment la un element strămoș, chiar și corpul, și puteți folosi proprietatea țintă / srcElement asupra obiectului evenimentului pentru a afla care element de adâncime a fost făcut clic. Aceasta se numește Delegare de evenimente. Iată un exemplu inutil:

Iată câteva coduri HTML:

 
  • Acasă
  • portofoliul
  • despre
  • a lua legatura

Putem folosi delegarea evenimentului pentru a face față clicurilor fiecăruia Li:

 funcția de navigare (e) var el = e.target || e.srcElement; switch (el.id) caz "home": alertă ("du-te acasă"); pauză; caz "portofoliu": alertă ("verificați produsele mele"); pauză; cazul "despre": alertă ("toate aceste detalii dezgustătoare"); pauză; caz "contact": alertă ("Te-am flatat că vrei să vorbești"); pauză; implicit: alertă ("cum ai ajuns aici?");  var nav = document.getElementById ("nav"); addEvent (nav, clic, navigare);

Folosim o instrucțiune switch / case pentru a vedea id-ul elementului cu un click mai adânc. Apoi, facem ceva în consecință.


Concluzie

Deci, acum poți purta evenimente JavaScript cu cele mai bune dintre ele. Distrează-te cu el și puneți întrebările în comentarii!

Cod