Quasi tutto ciò che fai in JavaScript dovrebbe iniziare quando succede qualcosa: l'utente fa clic su un pulsante, passa sopra un menu, preme un tasto, ti viene l'idea. È piuttosto semplice fare con librerie come jQuery, ma sai come collegare eventi in JavaScript non formattato? Oggi ti insegnerò proprio questo!
Gestire eventi JavaScript non è scienza missilistica. Certo, ci sono differenze tra i browser (cosa ti aspettavi?), Ma una volta capito e costruito le tue personali funzioni di supporto anche per il campo di gioco, sarai contento che tu lo sappia. Anche se pensi ancora di usare una libreria per questo tipo di cose, è bello sapere cosa sta succedendo sotto la superficie. Eccoci qui.
La gestione degli eventi più semplice in JavaScript è la gestione degli eventi di Livello 0. È piuttosto semplice: assegna la tua funzione alla proprietà dell'evento sull'elemento. Osservare:
var element = document.getElementById ('myElement'); element.onclick = function () alert ('la tua funzione qui'); ;
Una volta ottenuto l'elemento, imposto il al clic
proprietà uguale a una funzione. Ora, quando elemento
viene cliccato, quella funzione verrà eseguita e vedremo una finestra di avviso.
Ma come sapevo usare al clic
? È possibile ottenere un elenco di eventi disponibili su Wikipedia. Il bello del metodo Level 0 è che è supportato su tutti i browser oggi ampiamente utilizzati. Lo svantaggio è che puoi registrare ogni evento una volta sola con ciascun elemento. Quindi questo causerà solo un avviso:
element.onclick = function () alert ('funzione 1'); ; element.onclick = function () alert ('I override function 1');
Solo la seconda funzione verrà eseguita quando si fa clic sull'elemento, perché abbiamo riassegnato la proprietà onclick. Per rimuovere un gestore di eventi, possiamo semplicemente impostarlo su null.
element.onclick = null;
Sebbene fornisca solo funzionalità di base, il supporto coerente su tutti i browser rende l'evento di Livello 0 la gestione di un'opzione valida per progetti super-semplici.
Ora che ti stai riscaldando negli eventi JavaScript, discutiamo di due aspetti importanti prima di passare a tecniche migliori: l'oggetto evento e il Questo
parola chiave. Quando viene eseguito un evento, ci sono molte informazioni sull'evento che potresti voler sapere: quale tasto è stato premuto? quale elemento è stato cliccato? l'utente ha fatto clic con il pulsante sinistro, destro o centrale? Tutti questi dati e altro ancora sono memorizzati in un oggetto evento. Per tutti i browser eccetto Internet Explorer, è possibile accedere a questo oggetto passandolo come parametro alla funzione di gestione. In IE, puoi ottenerlo dalla variabile globale window.event
. Non è difficile risolvere questa differenza.
function myFunction (evt) evt = evt || window.event; / * ... * / element.onclick = myFunction;
myFunction
accetta il parametro evento per tutti i browser validi e li riassegniamo a window.event
Se EVT
non esiste Vedremo alcune delle proprietà dell'oggetto evento un po 'più tardi.
Il Questo
il keywork è importante nelle funzioni di gestione degli eventi; si riferisce all'elemento che ha ricevuto l'evento.
element.onclick = function () this.style.backgroundColor = 'red'; // same as element.style.backgroundColor = 'red';
Sfortunatamente, in Internet Explorer, Questo
non si riferisce all'elemento recitato; si riferisce all'oggetto finestra. Questo è inutile, ma vedremo un modo per porvi rimedio un po '.
La gestione degli eventi di livello 2 è la specifica W3C per gli eventi DOM. È abbastanza semplice, in realtà.
element.addEventListener ('mouseover', myFunction, false);
Il metodo è chiamato addEventListener
. Il primo parametro è il tipo di evento che vogliamo ascoltare. Solitamente, è lo stesso nome degli eventi di Livello 0, senza il prefisso 'on'. Il secondo parametro è un nome di funzione o la funzione stessa. Il parametro finale determina se catturiamo o no; discuteremo di questo in un momento.
Uno dei grandi vantaggi dell'uso addEventListener
è che ora possiamo assegnare più eventi per un singolo evento su un singolo elemento:
element.addEventListener ('dblclick', logSuccessToConsole, false); element.addEventListener ('dblclick', function () console.log ('questa funzione non sovrascrive la prima.');, false);
Per rimuovere questi gestori, utilizzare la funzione removeEventListener
. Quindi, per rimuovere la funzione che abbiamo aggiunto sopra, facciamo questo:
element.removeEventListener ('dblclick', logSuccessToConsole, false);
Il parametro finale in addEventListner
e removeEventListener
è un booleano che definisce se spariamo all'evento nello stadio di cattura o gorgogliante. Ecco cosa significa:
Quando fai clic su un elemento, fai anche clic su ognuno dei suoi elementi antenati.
Salva lavoro
Se clicco sul campata # salva
, Ho anche fatto clic div # barra degli strumenti
, div # involucro
, e corpo
. Quindi, se qualcuno di questi elementi ha ascoltatori di eventi che ascoltano i clic, verranno chiamate le loro rispettive funzioni. Ma quale ordine dovrebbero essere chiamati? Questo è ciò che decide l'ultimo parametro. Nella specifica W3C, il nostro evento click sarebbe iniziato da corpo
e spostati lungo la catena finché non raggiunge il campata # salva
; questo è il palcoscenico che cattura. Quindi, va dal campata # salva
di nuovo su corpo
; questo è il palcoscenico gorgogliante. È facile da ricordare, perché le bolle fluttuano verso l'alto. Bolla di tutti gli eventi; quella tabella di Wikipedia ti dirà quali sono quelli che fanno e quali no.
Quindi se il parametro capture è impostato su vero
, l'evento verrà attivato durante la discesa; se è impostato su falso
, verrà attivato durante il passaggio.
Potresti aver notato che, finora, tutti i miei esempi hanno impostato l'acquisizione su false, quindi l'evento viene attivato nella fase di bubbling. Questo perché Internet Explorer non ha una fase di acquisizione. In IE, gli eventi hanno solo bolle.
IE ha il suo modo proprietario di lavorare con gli eventi. Utilizza attachEvent
.
element.attachEvent ('onclick', runThisFunction);
Dal momento che gli eventi IE si limitano a generare bolle, non è necessaria la terza variabile. I primi due sono gli stessi di addEventListener
, con la grande eccezione che IE richiede il prefisso "on" per il tipo di evento. Naturalmente, con questo modello è possibile assegnare più eventi di un tipo a un singolo elemento. Per rimuovere eventi, utilizzare detachEvent
.
element.detachEvent ('onclick', runThisFunction);
Che cosa succede se i tuoi elementi non vogliono che i loro genitori scoprano i loro eventi? Non è difficile da nascondere. In IE, usi il cancelBubble
proprietà sull'oggetto evento che viene passato alla funzione chiamata. Per il resto, puoi usare il stopPropogation
metodo, anche sull'oggetto evento.
e.cancelBubble = true; if (e.stopPropagation) e.stopPropagation ();
Il stopPropogation
il metodo fermerà anche gli eventi nelle loro tracce durante la fase di cattura.
Sarei disposto a scommettere che la maggior parte delle proprietà sull'oggetto evento andrà inutilizzata, ma ci sono alcune scelte che hai trovato inestimabili. Diamo un'occhiata a quei pochi.
Il bersaglio
la proprietà è l'elemento più profondo su cui è stato fatto clic. Nell'immagine sopra, puoi vedere che ho cliccato Pulsante h1 #
. In IE, questa proprietà viene chiamata srcElement
; per ottenere questa proprietà, fai qualcosa di simile a questo:
var target = e.target || e.srcElement;
Il currentTarget
la proprietà è l'elemento che ha l'evento in questo momento. In quello screenshot, il currentTarget
è div # involucro
. Ciò significa che ho fatto clic Pulsante h1 #
, ma l'oggetto evento è stato registrato nella console nella funzione chiamata da div # involucro
L'ascoltatore di eventi.
Ma questo ti farà passare un ciclo: IE non ha una proprietà currentTarget o qualcosa del genere. Ricordando il fatto che IE non ha nemmeno lasciato Questo
uguale all'elemento che innesca l'evento, questo significa che non abbiamo modo di ottenere l'elemento che ha innescato l'evento quando è in corso un bubbling (nel senso che è stato fatto clic su un discendente dell'elemento). Confuso? Forse un esempio aiuterà: se, in Internet Explorer, abbiamo questo HTML ...
Pulsante
... e questo gestore di eventi ...
var par = document.getElementById ('parent'); parent.attachEvent ('onclick', doSomething);
... quindi, quando clicchiamo sul arco # bambino
e l'evento bolle fino a div # genitore
, non abbiamo modo dall'interno della funzione fare qualcosa
per ottenere l'elemento (in questo caso, div # genitore
) l'evento è stato attivato.
Ci sono altre proprietà sull'oggetto evento che troverai utili, a seconda dei casi. Su un evento di tastiera, (keyup, keydown, keypress), sarai il chiave
e il charCode
. Sarai in grado di dire se l'utente ha premuto il tasto alt, shift o ctrl (cmd) mentre si preme / si fa clic. Esplora gli oggetti evento di diversi eventi e guarda con cosa devi lavorare!
Abbiamo riscontrato due problemi principali nel nostro studio degli eventi fino ad ora.
currentTarget
proprietà, e il Questo
l'oggetto fa riferimento all'oggetto della finestra.Per risolvere questi problemi, creiamo due funzioni con supporto per browser, una per collegare eventi e una per rimuoverle.
Inizieremo con Aggiungi evento
; ecco il primo round:
var addEvent = function (element, type, fn) if (element.attachEvent) element.attachEvent ('on' + type, fn); else element.addEventListener (type, fn, false);
Sto assegnando una funzione anonima alla variabile Aggiungi evento
per ragioni che vedrai tra un minuto. Tutto quello che dobbiamo fare è controllare se l'elemento ha il attachEvent
metodo. Se lo fa, siamo in IE e useremo questo metodo. Se no, possiamo usare addEventListener
.
Tuttavia, ciò non risolve il fatto che non abbiamo modo di accedere all'elemento padre dell'evento in IE. Per fare ciò, renderemo la funzione un attributo sull'elemento; in questo modo, è percepito come un metodo dell'elemento, e Questo
sarà uguale all'elemento. Sì, lo so, brillante, non è vero? Beh, non posso prendermi alcun merito: questa idea viene da un post sul blog di John Resig.
var addEvent = function (element, type, fn) if (element.attachEvent) element ['e' + type + fn] = fn; element [type + fn] = function () element ['e' + type + fn] (window.event); element.attachEvent ('on' + tipo, elemento [tipo + fn]); else element.addEventListener (type, fn, false);
La prima linea in più (element ['e' + type + fn] = fn;
) rende la funzione un metodo dell'elemento, in modo che Questo
ora sarà uguale all'elemento. La seconda riga è una funzione che esegue il metodo, passando nell'oggetto window.event. Questo ti risparmia il passaggio extra di verifica del parametro dell'oggetto evento all'interno della tua funzione. Infine, nota che abbiamo modificato il parametro della funzione in attachEvent
metodo a elemento [tipo + fn]
.
Questo risolve i nostri due problemi. Ora possiamo usare il nostro Aggiungi evento
funziona in tutti i browser con la maggior esperienza possibile. Ma c'è un po 'di ottimismo che vorremmo fare.
Notare che ogni volta il nostro Aggiungi evento
la funzione è chiamata, controlla il attachEvent
metodo. Non c'è motivo per cui dovremmo controllarlo più volte, indipendentemente da quanti eventi vogliamo registrare. Possiamo usare un trucco elegante che ci permetterà di riscrivere Aggiungi evento
.
var addEvent = function (el, type, fn) if (el.attachEvent) addEvent = function (el, type, fn) el ['e' + type + fn] = fn; el [tipo + fn] = funzione () el ['e' + tipo + fn] (window.event); ; el.attachEvent ('on' + tipo, el [tipo + fn]); else addEvent = function (el, type, fn) el.addEventListener (type, fn, false); addEvent (el, type, fn);
Ora, se il Aggiungi evento
il metodo è stato trovato, lo riscriveremo Aggiungi evento
per includere solo le parti IE; in caso contrario, includeremo solo le buone parti del browser.
Nostro removeEvent
la funzione sarà molto simile:
var removeEvent = function (element, type, fn) if (element.detachEvent) removeEvent = function (element, type, fn) element.detachEvent ('on' + type, el [tipo + fn]); element [type + fn] = null; else removeEvent = function (element, type, fn) element.removeEventListener (type, fn, false); removeEvent (element, type, fn);
Questo è tutto per le funzioni degli eventi cross-browser. C'è una cosa che non mi piace di loro, però: le funzioni non sono metodi degli elementi; invece, l'elemento è un parametro. So che è solo una questione di stile, ma mi piace
btn.addEvent ('click', doThis);
meglio di
addEvent (btn, 'click', doThis);
Potremmo fare questo avvolgendo le nostre funzioni in questo:
var E = Element.prototype; E.addEvent = function (type, fn) addEvent (this, type, fn); E.removeEvent = function (type, fn) removeEvent (this, type, fn);
Questo funzionerà su tutti i browser moderni, così come su IE8; IE7 e IE6 si soffocano Elemento
. Dipende dal tuo pubblico; Prendere o lasciare!
Ora che sai tutto sugli eventi JavaScript, non precipitarti e riempire il tuo prossimo progetto con gli ascoltatori di eventi. Se hai molti elementi che rispondono allo stesso tipo di evento (ad esempio, fai clic), è più saggio approfittare del bubbling. È sufficiente aggiungere un listener di eventi a un elemento antenato, incluso il corpo, e utilizzare la proprietà target / srcElement sull'oggetto evento per determinare quale elemento più profondo è stato selezionato. Questo è chiamato Event Delegation. Ecco un esempio inutile:
Ecco alcuni HTML:
Possiamo utilizzare la delega degli eventi per gestire i clic per ciascuno Li
:
function navigation (e) var el = e.target || e.srcElement; switch (el.id) case 'home': alert ('vai a casa'); rompere; caso 'portfolio': alert ('check out my products'); rompere; caso 'about': alert ('tutti quei dettagli disgustosi'); rompere; caso "contatto": avviso ("Sono lusingato che ti piacerebbe parlare"); rompere; default: alert ('come sei arrivato?'); var nav = document.getElementById ('nav'); addEvent (nav, 'click', navigazione);
Usiamo un'istruzione switch / case per esaminare l'id dell'elemento cliccato più profondo. Quindi, facciamo qualcosa di conseguenza.
Così ora puoi impugnare gli eventi JavaScript con il meglio di loro. Divertiti con esso e fai tutte le domande nei commenti!