Da jQuery a JavaScript un riferimento

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.


Prima di iniziare

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

1 - $ ( '# Container');

Questa chiamata di funzione interrogherà il DOM per l'elemento con un id di contenitore, e creare un nuovo jQuery oggetto.

JavaScript moderno

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.

eredità

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.


2 - . $ ( '# 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.

JavaScript moderno

var lis = document.querySelectorAll ('# container li');

querySelectorAll tornerà tutti elementi che corrispondono al selettore CSS specificato.

Limitazioni del selettore

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.

eredità

var lis = document.getElementById ('container'). getElementsByTagName ('li');

3 - $ ('a'). on ('clic', fn);

In questo esempio, stiamo allegando a clic listener di eventi per tutti i tag di ancoraggio nella pagina.

JavaScript moderno

[]. 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.

eredità

var anchors = document.getElementsbyTagName ('a'); addEvent (anchor, 'click', fn);

4 - $ ('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.

JavaScript moderno

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.

eredità

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.


5 - ( '# Box') $ addClass ( 'wrap.');

jQuery fornisce un'utile API per modificare i nomi delle classi su un insieme di elementi.

JavaScript moderno

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

eredità

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?


6 - . $ ( '# List') accanto ();

jQuery di Il prossimo il metodo restituirà l'elemento che segue immediatamente l'elemento corrente nel set avvolto.

JavaScript moderno

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.

eredità

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.


7 - $ ('
') .AppendTo (' body ');

Oltre a interrogare il DOM, jQuery offre anche la possibilità di creare e iniettare elementi.

JavaScript moderno

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

8 - $ (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.

JavaScript moderno

document.addEventListener ('DOMContentLoaded', function () // divertirsi);

Standardizzato come parte di HTML5, il DOMContentLoaded l'evento si attiva non appena il documento è stato analizzato.

eredità

// 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.


9 - $ ('. 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.

JavaScript moderno

[] .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.

eredità

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.


10 - $ ()

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.

JavaScript moderno

var $ = function (el) return document.querySelectorAll (el); ; // Usage = $ ('. Box');

Notare che $ è semplicemente un puntatore a un carattere per document.querySelector. Fa risparmiare tempo!

eredità

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!


Sommario

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.