Enten vi liker det eller ikke, blir flere og flere utviklere introdusert til verden av JavaScript gjennom jQuery først. På mange måter er disse nykommerne de heldige. De har tilgang til en mengde nye JavaScript-APIer, noe som gjør prosessen med DOM-traversal (noe som mange folk er avhengige av jQuery for) betydelig enklere. Dessverre vet de ikke om disse APIene!
I denne artikkelen tar vi en rekke vanlige jQuery-oppgaver, og konverterer dem til både moderne og eldre JavaScript.
Moderne vs Legacy - For hvert element i listen nedenfor finner du den moderne "cool kids" -veien for å oppnå oppgaven, og arven, "gjør gamle nettlesere glade" -versjonen. Valget du velger for dine egne prosjekter, vil i stor grad avhenge av dine besøkende.
Vær oppmerksom på at noen av arven eksempler i denne artikkelen vil gjøre bruk av en enkel, kryssbrowser, addEvent
funksjon. Denne funksjonen sikrer ganske enkelt at både den W3C-anbefalte hendelsesmodellen, addEventListener
, og Internet Explorer arv attachEvent
er normalisert.
Så når jeg refererer til addEvent (els, event, handler)
i arvenes kodestykker nedenfor, blir følgende funksjon referert til.
var addEvent = (funksjon () var filter = funksjon (el, type, fn) for (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');
Denne funksjonen samtalen vil spørre DOM for elementet med en id
av container
, og opprett en ny jQuery
gjenstand.
var container = document.querySelector ('# container');
querySelector
er en del av Selectors API, som gir oss muligheten til å spørre DOM ved hjelp av CSS selectors som vi allerede er kjent med.
Denne spesielle metoden vil returnere det første elementet som samsvarer med den valgte väljeren.
var container = document.getElementById ('container');
Vær særlig oppmerksom på hvordan du refererer til elementet. Når du bruker getElementById
, Du overfører verdien alene, mens, med querySelector
, en CSS velger er forventet.
. $ ( '# Container') finne ( 'li');
Denne gangen er vi ikke på jakt etter et enkelt element; I stedet fanger vi et hvilket som helst antall listeposter som er etterkommere av #container
.
var lis = document.querySelectorAll ('# container li');
querySelectorAll
vil returnere alle elementer som samsvarer med den angitte CSS-väljeren.
Mens nesten alle relevante nettlesere støtter Selectors API, vil de spesifikke CSS-valgene du passerer, fremdeles være begrenset til nettleserens evne. Oversettelse: Internet Explorer 8 støtter bare CSS 2.1-valg.
var lis = document.getElementById ('container'). getElementsByTagName ('li');
$ ('a'). på ('klikk', fn);
I dette eksemplet knytter vi en klikk
hendelselytter til alle ankerkoder på siden.
[] .forEach.call (document.querySelectorAll ('a'), funksjon (el) el.addEventListener ('klikk', funksjon () // anker ble klikket, falsk););
Ovennevnte kutt ser skummelt ut, men det er ikke så ille. Fordi querySelectorAll
returnerer en statisk NodeList
heller enn en Array
, Vi kan ikke direkte få tilgang til metoder, som for hver
. Dette løses ved å ringe for hver
på Array
objekt, og passerer resultatene av querySelectorAll
som dette
.
var ankre = document.getElementsbyTagName ('a'); addEvent (ankre, klikk ", fn);
$ ('ul'). på ('klikk', 'a', fn);
Ahh - dette eksemplet er litt annerledes. Denne gangen bruker jQuery-kuttet hendelsesdelegasjon. De klikk
lytteren blir brukt på alle uordnede lister, men tilbakekallingsfunksjonen vil bare brenne hvis målet (det som brukeren klikket spesielt på) er et ankermerke.
document.addEventListener ('klikk', funksjon (e) hvis (e.target.matchesSelector ('ul a')) // fortsett, feil);
Teknisk er denne vanilla JavaScript-metoden ikke den samme som jQuery-eksemplet. I stedet er det knyttet hendelseslytteren direkte til dokument
. Den bruker deretter den nye matchesSelector
metode for å avgjøre om mål
- noden som ble klikket - samsvarer med den valgte väljeren. På denne måten knytter vi en enkelt hendelse lytter, i stedet for mange.
Vær oppmerksom på at alle nettlesere implementerer på tidspunktet for denne skrivingen matchesSelector
via sine respektive prefikser: mozMatchesSelector
, webkitMatchesSelector
, etc. For å normalisere metoden kan man skrive:
var kamper; (funksjon (doc) matches = doc.matchesSelector || doc.webkitMatchesSelector || doc.mozMatchesSelector || doc.oMatchesSelector || doc.msMatchesSelector;) (document.documentElement); document.addEventListener ('klikk', funksjon (e) hvis (matches.call (e.target, 'ul a')) // fortsett, falsk);
Med denne teknikken, i Webkit, vil kamper referere til
webkitMatchesSelector
, og i Mozilla,mozMatchesSelector
.
var uls = document.getElementsByTagName ('ul'); addEvent (uls, 'klikk', funksjon () var target = e.target || e.srcElement; hvis (mål && target.nodeName === 'A') // fortsett);
Som en tilbakebetaling bestemmer vi om nodename
Egenskapen (navnet på målelementet) er lik vår forespurte forespørsel. Vær særlig oppmerksom på at eldre versjoner av Internet Explorer noen ganger spiller etter egne regler - som for eksempel barnet som spiser play-doh i lunsjtid. Du vil ikke kunne få tilgang mål
direkte fra begivenhet
gjenstand. I stedet vil du se etter event.srcElement
.
$ ( '# Box') addClass ( 'wrap.');
jQuery gir en nyttig API for å endre klassenavn på et sett med elementer.
document.querySelector ( '# box') classList.add ( 'wrap.');
Denne nye teknikken bruker den nye classList
API til Legg til
, fjerne
, og veksle
klassenavn.
var container = document.querySelector ('# box'); container.classList.add ( 'wrap'); container.classList.remove ( 'wrap'); container.classList.toggle ( 'wrap');
var boks = document.getElementById ('boks'), hasClass = funksjon (el, cl) var regex = nytt RegExp ('(?: \\ s | ^)' + cl + '(?: \\ s | $ ) '); returnere! el.className.match (regex); , addClass = funksjon (el, cl) el.className + = "+ cl;, removeClass = funksjon (el, cl) var regex = ny RegExp ('(?: \\ s | ^)' + cl + '(?: \\ s | $)'); el.className = el.className.replace (regex, "); , toggleClass = funksjon (el, cl) hasClass (el, cl)? removeClass (el, cl): addClass (el, cl); ; addClass (boks, 'drago'); removeClass (boks, 'drago'); toggleClass (boks, 'drago'); // hvis elementet ikke har en klasse av 'drago', legg til en.
Fallback-teknikken krever bare litt mer arbeid, ay?
. $ ( '# Listen') neste ();
jQuery neste
Metoden vil returnere elementet som umiddelbart følger det nåværende elementet i det pakkede settet.
var neste = document.querySelector ('# list'). nextElementSibling; // IE9
nextElementSibling
vil referere spesifikt til det neste element node, snarere enn noen node (tekst, kommentar, element). Dessverre støtter ikke Internet Explorer 8 og under det.
var list = document.getElementById ('liste'), next = list.nextSibling; // vi vil ha neste elementskode ... ikke tekst. mens (next.nodeType> 1) next = next.nextSibling;
Det er et par måter å skrive dette på. I dette eksemplet oppdager vi Nodetype
av noden som følger det angitte elementet. Det kan være tekst, element eller til og med en kommentar. Som vi spesielt trenger det neste elementet, ønsker vi a Nodetype
av 1
. Hvis next.nodeType
returnerer et tall som er større enn 1
, vi burde hoppe over det og fortsette, da det er sannsynligvis en tekstknute.
$ ('') .AppendTo (' body ");
I tillegg til å spørre DOM, tilbyr jQuery også muligheten til å lage og injisere elementer.
var div = document.createElement ('div'); div.id = 'box'; document.body.appendChild (div);
Det er ikke noe moderne om dette eksempelet; Det er hvordan vi har oppnådd prosessen med å lage og injisere elementer i DOM i lang, lang tid.
Du må sannsynligvis legge til innhold i elementet, i så fall kan du enten bruke innerhtml
, eller createTextNode
.
div.appendChild (document.createTextNode ('wacka wacka')); // eller div.innerHTML = 'wacka wacka';
$ (Document) .ready (fn)
jQuery document.ready
metoden er utrolig praktisk. Det tillater oss å begynne å utføre kode så snart som mulig etter at DOM er lastet inn.
document.addEventListener ('DOMContentLoaded', funksjon () // ha det gøy);
Standardisert som en del av HTML5, the DOMContentLoaded
hendelsen vil brenne så snart dokumentet er fullført, analysert.
// http://dustindiaz.com/smallest-domready-function ready (cb) /in/.test(document.readyState) // in = loadINg? setTimeout ('ready (' + cb + ')', 9): cb (); klar (funksjon () // ta tak i noe fra DOM);
Fallback-løsningen, hver ni millisekunder, vil oppdage verdien av document.readyState
. Hvis "loading" returneres, har dokumentet ennå ikke blitt fullstendig analysert (/in/.test ()
. En gang den har, skjønt, document.readyState
vil være lik "fullført", på hvilket tidspunkt brukerens tilbakeringingsfunksjon utføres.
$ ('.boks'). css ('farge', 'rød');
Hvis mulig, legg alltid til en klasse
til et element når du trenger å gi spesiell styling. Men noen ganger vil stylingen bli bestemt dynamisk, i så fall må den settes inn som et attributt.
[] .forEach.call (document.querySelectorAll ('.box'), funksjon (el) el.style.color = 'rød'; // eller legg til en klasse);
Nok en gang bruker vi [] .ForEach.call ()
teknikk for å filtrere gjennom alle elementene med en klasse av eske
, og gjør dem røde, via stil
gjenstand.
var box = document.getElementsByClassName ('box'), // referer til eksempel # 10 nedenfor for en kryssbrowser løsning i = box.length; mens (jeg--> 0 && (boks [i] .style.color = 'rød'));
Denne gangen blir vi litt vanskelige med samtidig som
sløyfe. Ja, det er litt snarky, ikke sant? I hovedsak mimler vi:
var i = 0, len; for (len = box.length; i < len; i++ ) box[i].style.color = 'red';
Men da vi bare trenger å utføre en enkelt handling, kan vi lagre et par linjer. Merk at lesbarhet er langt viktigere enn å lagre to linjer - derav min "snarky" referanse. Likevel er det alltid morsomt å se hvordan kondensert du kan lage sløyfer. Vi er utviklere; Vi gjør slike ting for moro skyld! Uansett, vær så snill å holde fast ved til
uttalelsesversjon.
$ ()
Det er klart at vår hensikt er ikke å gjenskape hele jQuery API. Vanligvis for ikke-jQuery-prosjekter, $
eller $$
funksjonen brukes som stenografi for å hente ett eller flere elementer fra DOM.
var $ = funksjon (el) return document.querySelectorAll (el); ; // Bruk = $ ('. Boks');
Legg merke til det $
er rett og slett et tegn på en tegn til document.querySelector
. Det sparer tid!
hvis (! document.getElementsByClassName) document.getElementsByClassName = funksjon (kl, tag) var els, matches = [], i = 0, len, regex = nytt RegExp ('(?: \\ s | ^)' + cl + '(?: \\ s | $)'); // Hvis ikke noe navn er oppgitt, // vi må ta tak i EVERY element fra DOM els = document.getElementsByTagName (tag || "*"); hvis (! els [0]) returnerer falsk; for (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
Dessverre er arvmetoden ikke helt så minimal. Ærlig, på dette tidspunktet bør du bruke et bibliotek. jQuery er svært optimalisert for å jobbe med DOM, og det er derfor det er så populært! Eksemplet ovenfor vil sikkert fungere, men det støtter ikke komplekse CSS-selektorer i eldre nettlesere; den oppgaven er bare litt mer komplisert!
Det er viktig for meg å merke seg at jeg ikke oppfordrer deg til å forlate jQuery. Jeg bruker det i nesten alle mine prosjekter. Når det er sagt, ikke alltid være villig til å omfavne abstraksjoner uten å ta litt tid på å undersøke den underliggende koden.
Jeg vil gjerne at dette innlegget skal tjene som et levende dokument, av forskjellige slag. Hvis du har noen av dine egne (eller forbedringer / avklaringer for mine eksempler), legg igjen en kommentar nedenfor, og jeg vil sporadisk oppdatere denne innleggingen med nye elementer. Bookmark denne siden nå! Til slutt vil jeg sende et hat-tips til dette settet med eksempler, som tjente som drivkraft for dette innlegget.