Che ci piaccia o no, sempre più sviluppatori vengono introdotti nel mondo di JavaScript attraverso jQuery per primi. In molti modi, questi nuovi arrivati sono i più fortunati. Hanno accesso a una pletora di nuove API JavaScript, che rendono notevolmente più semplice il processo di attraversamento DOM (qualcosa che molte persone dipendono da jQuery). Sfortunatamente, non sanno di queste API!
In questo articolo, prenderemo una serie di attività comuni di jQuery e le convertiremo in JavaScript moderno e legacy.
Modern vs. Legacy - Per ogni elemento nella lista qui sotto, troverai il modo moderno, "cool kids" per portare a termine il compito, e la versione precedente, "make old browser happy". La scelta che scegli per i tuoi progetti dipenderà in gran parte dai tuoi visitatori.
Si prega di notare che alcuni dei eredità esempi in questo articolo faranno uso di un semplice browser multipiattaforma, Aggiungi evento
funzione. Questa funzione assicurerà semplicemente che sia il modello di eventi raccomandato dal W3C, addEventListener
, e l'eredità di Internet Explorer attachEvent
sono normalizzati.
Quindi, quando mi riferisco a addEvent (els, evento, gestore)
nei frammenti di codice legacy riportati di seguito, viene utilizzata la seguente funzione.
var addEvent = (function () var filter = function (el, type, fn) per (var i = 0, len = el.length; i < len; i++ ) addEvent(el[i], type, fn); ; if ( document.addEventListener ) return function (el, type, fn) if ( el && el.nodeName || el === window ) el.addEventListener(type, fn, false); else if (el && el.length) filter(el, type, fn); ; return function (el, type, fn) if ( el && el.nodeName || el === window ) el.attachEvent('on' + type, function () return fn.call(el, window.event); ); else if ( el && el.length ) filter(el, type, fn); ; )(); // usage addEvent( document.getElementsByTagName('a'), 'click', fn);
$ ( '# Container');
Questa chiamata di funzione interrogherà il DOM per l'elemento con un id
di contenitore
, e creare un nuovo jQuery
oggetto.
var container = document.querySelector ('# container');
querySelector
fa parte dell'API Selectors, che ci consente di interrogare il DOM utilizzando i selettori CSS con cui abbiamo già familiarità.
Questo particolare metodo restituirà il primo elemento che corrisponde al selettore passato.
var container = document.getElementById ('container');
Prestare particolare attenzione al modo in cui si fa riferimento all'elemento. Quando si usa getElementById
, tu passi il valore da solo, mentre, con querySelector
, è previsto un selettore CSS.
. $ ( '# Container') trova ( 'li');
Questa volta, non stiamo cercando un singolo elemento; invece, stiamo catturando qualsiasi numero di elementi di elenco di cui sono discendenti #contenitore
.
var lis = document.querySelectorAll ('# container li');
querySelectorAll
tornerà tutti elementi che corrispondono al selettore CSS specificato.
Mentre quasi tutti i browser rilevanti supportano l'API dei selettori, i selettori CSS specifici che si passano sono ancora limitati alla capacità del browser. Traduzione: Internet Explorer 8 supporterà solo i selettori CSS 2.1.
var lis = document.getElementById ('container'). getElementsByTagName ('li');
$ ('a'). on ('clic', fn);
In questo esempio, stiamo allegando a clic
listener di eventi per tutti i tag di ancoraggio nella pagina.
[]. forEach.call (document.querySelectorAll ('a'), function (el) el.addEventListener ('click', function () // anchor was clickked, false););
Lo snippet sopra sembra spaventoso, ma non è male. Perché querySelectorAll
restituisce una statica NodeList
piuttosto che un schieramento
, non possiamo accedere direttamente ai metodi, come per ciascuno
. Questo è stato risolto chiamando per ciascuno
sul schieramento
oggetto e passando i risultati di querySelectorAll
come Questo
.
var anchors = document.getElementsbyTagName ('a'); addEvent (anchor, 'click', fn);
$ ('ul'). on ('click', 'a', fn);
Ahh: questo esempio è leggermente diverso. Questa volta, lo snippet jQuery utilizza la delega degli eventi. Il clic
ascoltatore viene applicato a tutti gli elenchi non ordinati, tuttavia, la funzione di callback verrà attivata solo se il target (su cui l'utente ha fatto clic in modo specifico) è un tag di ancoraggio.
document.addEventListener ('click', function (e) if (e.target.matchesSelector ('ul a')) // proceed, false);
Tecnicamente, questo metodo vanilla JavaScript non è lo stesso dell'esempio jQuery. Al contrario, collega il listener di eventi direttamente a documento
. Quindi usa il nuovo matchesSelector
metodo per determinare se il bersaglio
- il nodo su cui è stato fatto clic - corrisponde al selettore fornito. In questo modo, stiamo allegando un singolo listener di eventi, piuttosto che molti.
Si prega di notare che, al momento della stesura di questo documento, tutti i browser implementano matchesSelector
tramite i rispettivi prefissi: mozMatchesSelector
, webkitMatchesSelector
, ecc. Per normalizzare il metodo, si potrebbe scrivere:
partite varie; (function (doc) matches = doc.matchesSelector || doc.webkitMatchesSelector || doc.mozMatchesSelector || doc.oMatchesSelector || doc.msMatchesSelector;) (document.documentElement); document.addEventListener ('click', function (e) if (matches.call (e.target, 'ul a')) // proceed, false);
Con questa tecnica, in Webkit, le partite faranno riferimento a
webkitMatchesSelector
, e, in Mozilla,mozMatchesSelector
.
var uls = document.getElementsByTagName ('ul'); addEvent (uls, 'click', function () var target = e.target || e.srcElement; if (target && target.nodeName === 'A') // proceed);
Come fallback, determiniamo se il nodeName
proprietà (il nome dell'elemento di destinazione) è uguale alla nostra query desiderata. Presta particolare attenzione al fatto che le versioni precedenti di Internet Explorer a volte giocano secondo le proprie regole, un po 'come il bambino che mangia il gioco dozzina durante l'ora di pranzo. Non sarai in grado di accedere bersaglio
direttamente dal evento
oggetto. Invece, vorrai cercare event.srcElement
.
( '# Box') $ addClass ( 'wrap.');
jQuery fornisce un'utile API per modificare i nomi delle classi su un insieme di elementi.
document.querySelector ( '# box') classList.add ( 'wrap.');
Questa nuova tecnica usa il nuovo classList
API a Inserisci
, rimuovere
, e ginocchiera
nomi di classe.
var container = document.querySelector ('# box'); container.classList.add ( 'wrap'); container.classList.remove ( 'wrap'); container.classList.toggle ( 'wrap');
var box = document.getElementById ('box'), hasClass = function (el, cl) var regex = new RegExp ('(?: \\ s | ^)' + cl + '(?: \\ s | $ ) '); return !! el.className.match (regex); , addClass = function (el, cl) el.className + = "+ cl;, removeClass = function (el, cl) var regex = new RegExp ('(?: \\ s | ^)' + cl + '(?: \\ s | $)'); el.className = el.className.replace (regex, "); , toggleClass = function (el, cl) hasClass (el, cl)? removeClass (el, cl): addClass (el, cl); ; addClass (box, 'drago'); removeClass (box, 'drago'); toggleClass (box, 'drago'); // se l'elemento non ha una classe di 'drago', aggiungine uno.
La tecnica di fallback richiede solo un po 'di lavoro in più, ay?
. $ ( '# List') accanto ();
jQuery di Il prossimo
il metodo restituirà l'elemento che segue immediatamente l'elemento corrente nel set avvolto.
var next = document.querySelector ('# elenco'). nextElementSibling; // IE9
nextElementSibling
si riferirà specificamente al prossimo elemento nodo, piuttosto che qualsiasi nodo (testo, commento, elemento). Sfortunatamente, Internet Explorer 8 e versioni successive non lo supportano.
var list = document.getElementById ('list'), next = list.nextSibling; // vogliamo il nodo dell'elemento successivo ... non il testo. while (next.nodeType> 1) next = next.nextSibling;
Ci sono un paio di modi per scrivere questo. In questo esempio, stiamo rilevando il nodeType
del nodo che segue l'elemento specificato. Potrebbe essere testo, elemento o anche un commento. Poiché abbiamo specificamente bisogno del prossimo elemento, desideriamo a nodeType
di 1
. Se next.nodeType
restituisce un numero maggiore di 1
, dovremmo saltarlo e andare avanti, poiché probabilmente è un nodo di testo.
$ ('') .AppendTo (' body ');
Oltre a interrogare il DOM, jQuery offre anche la possibilità di creare e iniettare elementi.
var div = document.createElement ('div'); div.id = 'box'; document.body.appendChild (div);
Non c'è nulla di moderno in questo esempio; è come abbiamo realizzato il processo di creazione e iniezione di elementi nel DOM per molto, molto tempo.
Probabilmente dovrai aggiungere contenuto all'elemento, nel qual caso puoi utilizzare innerHTML
, o createTextNode
.
div.appendChild (document.createTextNode ('wacka wacka')); // o div.innerHTML = 'wacka wacka';
$ (Document) .ready (fn)
jQuery di document.ready
il metodo è incredibilmente conveniente. Ci consente di iniziare a eseguire il codice il più presto possibile dopo che il DOM è stato caricato.
document.addEventListener ('DOMContentLoaded', function () // divertirsi);
Standardizzato come parte di HTML5, il DOMContentLoaded
l'evento si attiva non appena il documento è stato analizzato.
// http://dustindiaz.com/smallest-domready-ever function ready (cb) /in/.test(document.readyState) // in = loadINg? setTimeout ('ready (' + cb + ')', 9): cb (); ready (function () // cattura qualcosa dal DOM);
La soluzione di fallback, ogni nove millisecondi, rileverà il valore di document.readyState
. Se viene restituito "caricamento", il documento non è stato ancora completamente analizzato (/in/.test ()
. Una volta che ha, però, document.readyState
sarà uguale a "completo", a quel punto viene eseguita la funzione di callback dell'utente.
$ ('. box'). css ('color', 'red');
Se possibile, aggiungi sempre un classe
a un elemento, quando è necessario fornire uno stile speciale. Tuttavia, a volte, lo stile viene determinato dinamicamente, nel qual caso deve essere inserito come attributo.
[] .forEach.call (document.querySelectorAll ('. box'), function (el) el.style.color = 'red'; // oppure aggiungi una classe);
Ancora una volta, stiamo usando il [] .ForEach.call ()
tecnica per filtrare tutti gli elementi con una classe di scatola
, e renderli rossi, tramite il stile
oggetto.
var box = document.getElementsByClassName ('box'), // fai riferimento all'esempio # 10 sotto per una soluzione cross-browser i = box.length; while (i--> 0 && (box [i] .style.color = 'red'));
Questa volta, stiamo diventando un po 'complicati con il mentre
ciclo continuo. Sì, è un po 'snarky, non è vero? In sostanza, stiamo imitando:
var i = 0, len; per (len = box.length; i < len; i++ ) box[i].style.color = 'red';
Tuttavia, poiché abbiamo solo bisogno di eseguire una singola azione, possiamo salvare un paio di linee. Si noti che la leggibilità è molto più importante del salvataggio di due righe - da qui il mio riferimento "snarky". Ciononostante, è sempre divertente vedere quanto condensato puoi creare i tuoi loop. Siamo sviluppatori; facciamo questo genere di cose per divertimento! In ogni caso, sentiti libero di attenersi al per
versione dell'affermazione.
$ ()
Chiaramente, la nostra intenzione non è quella di replicare l'intera API di jQuery. In genere, per progetti non jQuery, il $
o $$
la funzione è utilizzata come abbreviazione per il recupero di uno o più elementi dal DOM.
var $ = function (el) return document.querySelectorAll (el); ; // Usage = $ ('. Box');
Notare che $
è semplicemente un puntatore a un carattere per document.querySelector
. Fa risparmiare tempo!
if (! document.getElementsByClassName) document.getElementsByClassName = function (cl, tag) var els, matches = [], i = 0, len, regex = new RegExp ('(?: \\ s | ^)' + cl + '(?: \\ s | $)'); // Se non viene specificato alcun nome di tag, // dobbiamo prendere OGNI elemento dal DOM els = document.getElementsByTagName (tag || "*"); if (! els [0]) restituisce false; per (len = els.length; i < len; i++ ) if ( els[i].className.match(regex) ) matches.push( els[i]); return matches; // an array of elements that have the desired classname ; // Very simple implementation. We're only checking for an id, class, or tag name. // Does not accept CSS selectors in pre-querySelector browsers. var $ = function(el, tag) var firstChar = el.charAt(0); if ( document.querySelectorAll ) return document.querySelectorAll(el); switch ( firstChar ) case "#": return document.getElementById( el.slice(1) ); case ".": return document.getElementsByClassName( el.slice(1), tag ); default: return document.getElementsByTagName(el); ; // Usage $('#container'); $('.box'); // any element with a class of box $('.box', 'div'); // look for divs with a class of box $('p'); // get all p elements
Sfortunatamente, il metodo legacy non è così minimale. Onestamente, a questo punto, dovresti usare una libreria. jQuery è altamente ottimizzato per lavorare con il DOM, motivo per cui è così popolare! L'esempio sopra funzionerà sicuramente, tuttavia, non supporta i selettori CSS complessi nei browser più vecchi; quel compito è solo un pochino più complicato!
Per me è importante notare che non ti sto incoraggiando ad abbandonare jQuery. Lo uso in quasi tutti i miei progetti. Detto questo, non essere sempre disposti ad abbracciare le astrazioni senza dover dedicare un po 'di tempo alla ricerca del codice sottostante.
Mi piacerebbe che questa pubblicazione servisse da documento vivente. Se ne hai qualcuno di tuo (o miglioramenti / chiarimenti per i miei esempi), lascia un commento qui sotto, e aggiornerò sporadicamente questo post con nuovi elementi. Aggiungi subito questa pagina ai segnalibri! Infine, vorrei inviare una punta di cappello a questo set di esempi, che è servito da impeto per questo post.