Her er tingen: Hvis du ikke kan skjønne hvorfor du vil trenge et rammeverk som Ryggrad, så er det sjansene, det gjør du ikke! Kanskje du jobber utelukkende på enkle nettsteder eller grunnleggende WordPress-temaer; i disse tilfellene vil et strukturert JavaScript-rammeverk sannsynligvis være overkill.
Men det kommer sikkert å komme en dag når du innser at all den spaghettikoden er inne manus
Merkene nederst på siden din har plutselig blitt uhåndterlige. Ikke bare det, men på grunn av måten du strukturerte koden på, er det også umulig å teste. Gispe! Hva å gjøre?
Når den dagen oppstår - og det vil - peker nettleseren din på Backbonejs.org, og ta et skritt fremover, når du går videre til neste nivå i programmeringsmodigheten din.
Tenk på Backbone som et lite rammeverk (5.6kb, pakket) som gir struktur til dine applikasjoner. Ved å implementere sin egen smak av MVC-mønsteret (faktisk, mer som MV *), gir Backbone de nødvendige verktøyene for å skille dataene dine fra presentasjonen. Hvis du tenker på det, hvor de fleste av oss ofte snubler, er når vi desperat prøver å opprettholde våre data. Vanligvis resulterer dette i utallige DOM-spørringer, ettersom vi frantisk henter de nødvendige verdiene for å holde programmets presentasjon og data synkronisert. Det må være en bedre måte!
"Få sannheten din ut av DOM". - Jeremy Ashkenas (Skaperen av Backbone.js)
Løsningen, som skaperen av Backbone.js, Jeremy Ashkenas, så ofte talsmenn, er å slutte å binde dataene dine til DOM. Gjør visningen din gjenspeiler dataene dine, ikke omvendt!
Sannferdig er det sannsynligvis bedre hvis du ikke engang forsøker å konvertere dine eksisterende MVC-følsomheter over
Du vil ofte se Backbone, så vel som mange av sine søskenrammer, referert til som MV *, i stedet for MVC. Fordi konseptet med din standard server-side "controller" og "view" ikke overføres for godt til et JavaScript-rammeverk, kan dette ofte føre til forvirring. Det gjorde sikkert for meg!
Sannferdig er det sannsynligvis bedre hvis du ikke engang forsøker å konvertere dine eksisterende MVC-sensibiliteter over; det vil bare forvirre deg. En "visning" i Ruby on Rails er ikke den samme som en "visning" i Ryggrad. Eller, en "kontroller" i CodeIgniter har egentlig ikke en motstykke i Backbone. Faktisk finnes det ikke kontroller i Backbone! I stedet låner Backbone biter og biter fra andre rammer, og derfor refererer vi ofte til det som å være nærmere MVP (Model, View, Presenter) eller MV *: det er ikke MVC, og ikke helt MVP; det er sin egen smak.
La oss først avgjøre hvordan logikken deles i vår søknad. Justere vårt konsept om hvordan JavaScript skal struktureres, kan ta litt tid å tilpasse seg, så vær ikke bekymret hvis dette tar deg tid til å bryte deg rundt.
I Backbone er data representert gjennom en modell. For eksempel, vurder en Bilde
modell. Denne modellen vil definere planen for et bilde: hva er bildens kilde, dens beskrivelse, hvem er avbildet på bildet etc. Vi kan til og med søke om validering ved behov, via en valgfri validere
metode.
var Photo = Backbone.Model.extend (standard: src: 'images / placeholder.jpg', beskrivelse: 'My Image', folk: []);
Med tegningen på plass, kan vi nå sette opp vårt første bilde ved å lage en ny forekomst av Bilde
modell, slik som:
var photo = nytt bilde (src: 'images_22 / connected-to-the-backbone.jpg', beskrivelse: 'Med venner til middag', folk: ['John Doe', 'Rick James']);
Tada - du har laget din første modell. Skulle du måtte hente eller sette inn informasjon fra denne modellen, er det like enkelt som å bruke Backbone's getters og setters:
photo.toJSON (); // objekt som inneholder alle rekvisitter photo.get ('src'); // images_22 / connected-to-the-backbone.jpg photo.set ('src', 'images / new-path.jpg'); photo.get (src-); // images / new-path.jpg
I Backbone, som en best practice, er en visning ansvarlig for representasjonen av et enkelt DOM-element og eventuelle gjeldende barn, for eksempel et listeelement, eller div
- alt du vil. Dette inkluderer registrering av aktuelle maler, lytting og svar på hendelser, og overvåking av tilhørende modeller og samlinger for endringer.
La oss lage en ny visning for selve bildetaggen.
var ImageView = Ryggrad.View.extend (tagName: 'img', initialiser: funksjon () this.render ();, render: function () this. $ el.attr (src: this.model. få ('src'), alt: this.model.get ('description')););
Ikke la denne koden forvirre deg. Det er ganske lesbart og elegant. Vi tar det trinnvis.
Å begynne, TagNavn
angir hvilket DOM-element visningen representerer. I dette tilfellet definerer vi visningen for en enkelt img
element, skjønt, kunne vi like enkelt knytte det til et element som allerede finnes i DOM, via el
eiendom.
var ImageView = Ryggrad.View.extend (el: '# my-image');
Bak kulissene vil Backbone hente det angitte elementet (# My-bilde
) fra DOM, cache det, og gjør det tilgjengelig via ImageView.el
og Imageview. $ El
. Den sistnevnte versjonen, som du kanskje forventer, er elementet innpakket i jQuery (eller potensielt Zepto, hvis du foretrekker det biblioteket over jQuery).
Deretter kan du tenke på initial
metode som konstruktør. Når en ny forekomst av denne visningen er opprettet, kjøres denne metoden automatisk. Dette er det perfekte stedet å opprette nye instansvariabler, og abonnere på eventuelle modell- eller kontrollerhendelser.
Til slutt, gjengi
Metoden er ansvarlig for å konstruere produksjonen. I dette tilfellet vil det sette begge src
og alt
attributter av bildet som er lik dataene som er lagret i visningen er tilknyttet modell.
La oss lage en ny forekomst av Imageview
, og send inn noen data. I en virkelig applikasjon kan disse dataene komme fra et skjema eller noe lignende.
var photo = nytt bilde (src: 'images_22 / connected-to-the-backbone.jpg', beskrivelse: 'Med venner til middag', folk: ['John Doe', 'Rick James']); var imageView = ny ImageView (modell: photo); imageView.el; //
Dette kan være utrolig kraftig, hvis du tenker på det! I Ryggraden er det trivielt å oppdatere en visning når den respektive modellen er endret, forutsatt at det er ett-til-ett-forhold. La oss lytte etter når dataene (eller modellen) er endret. Når det er, bør vi oppdatere elementet tilsvarende.
Følgende kode kan legges til i initial
metode av Imageview
.
initialiser: funksjon () // Lytt etter når modellen er oppdatert this.model.on ('change', this.render, this); this.render (); , gjengi: funksjon () denne. $ el.attr (src: this.model.get ('src'), alt: this.model.get ('description'));
Undervurder ikke hvor effektiv denne PubSub implementeringen kan være. Når en modell er endret, gjør den en kunngjøring, så å si. "Alle som er interessert - jeg har nettopp blitt endret!" Innenfor vårt syn, med en enkelt linje med kode, kan vi abonnere på denne kunngjøringen, og svare på det ved å oppdatere bildens attributter.
this.model.on ('change', this.render, dette);
I dette tilfellet ringer vi igjen gjengi
metode, og generere attributter igjen.
La oss teste det.
var imageView = ny ImageView (modell: photo); imageView.el; // photo.set ('src', 'images_22 / connected-to-the-backbone.jpg'); imageView.el //
Utmerket! Skulle du trenge det, kan du også legge til DOM-nivå hendelse lyttere enkelt, via en arrangementer
Motta at Backbone automatisk vil jakte og sette for deg. Kanskje du vil redigere bildet når det klikkes:
hendelser: 'klikk': 'rediger', rediger: funksjon () // rediger bildet
Som denne visningen representerer en enkelt img
element, vi kan holde fast med klikk'
, Du vil imidlertid ofte finne det View.el
inneholder nestede barn. I disse tilfellene kan du spesifisere en velger etter hendelsestypen, slik som:
hendelser: 'klikk span': 'doSomething', doSomething: function ()
Ovennevnte kode, ved bruk av View.el
som kontekst, vil legge ved en klikkhendelse til et hvilket som helst barn span
s.
Hvilken god er en modell for et enkelt bilde? La oss lagre alle bildemodellene i en Bilder
samling. Tenk på samlinger som arrays med ekstra sukker og bekvemmelighetsmetoder, takket være Backbones eneste hardt avhengighet, Underscore.js.
var Photos = Backbone.Collection.extend (modell: Photo);
Ovenfor har vi tilknyttet Bilder
samling med Bilde
modell som vi allerede har opprettet. Dette angir at alle elementer i denne samlingen vil være forekomster av Bilde
modell.
Deretter oppretter vi vår forekomst, og sendes i noen få modeller for å komme oss i gang. I dette tilfellet er vi hardt kodende verdiene, men du kan like enkelt hente JSON fra serveren din.
var photos = nye bilder ([src: 'image1.jpg', beskrivelse: 'Vacation 2012', src: 'image2.jpg', beskrivelse: 'Min beste venn', src: 'image3.jpg' , beskrivelse: 'jubileumsfest']);
Legg merke til hvordan denne gangen ser det ut som om vi bare sender noen objekter til Bilder
samling. Men bak kulissene, hver gjenstand
i matrise
vil bli konvertert til a Bilde
modell.
I likhet med modeller vil samlinger kunngjøre eventuelle endringer, for eksempel når en modell legges til eller fjernes. Dette betyr at du kan lytte til, for eksempel, når et nytt element legges til samlingen. Når dette skjer, kan du kompensere ved å oppdatere DOM tilsvarende med det nye elementet.
this.collection.on ('add', this.appendItem);
I tillegg, som nevnt ovenfor, gir en samling mye sukker. For eksempel, la oss si at vi må ta tak i src
eiendom fra hver modell i samlingen. Det er en cinch med plukke
metode!
photos.pluck (src-); // ["image1.jpg", "image2.jpg", "image3.jpg"]
Legg merke til hvordan dataene våre til enhver tid er tilgjengelige. Vi trenger aldri å spørre DOM for å hente noen verdier. "Hold sannheten din ut av DOM."
Se under Underscore.js dokumentasjon for flere brukseksempler.
På dette tidspunktet har vi en samling bilder, men nå trenger vi en ny visning som vil være ansvarlig for presentasjonen av fotoboksen. Huske, Imageview
er bare ansvarlig for et enkelt bildeelement. La oss lage en ny visning for innpakningsliste over bilder.
var PhotosView = Backbone.View.extend (tagName: 'ul', className: 'photos', initialiser: funksjon () this.render (); render: function () var imageView; this.collection.forEach (funksjon (modell) imageView = new ImageView (modell: modell); dette. $ el.append ($ ('
Denne gangen lager vi visningen for innpakningen
element. Når vi ringer render ()
, Metoden vil filtrere gjennom alle modellene som er inkludert i den tilknyttede samlingen (tre, i vårt tilfelle), opprett en ny Imageview
for hver - som konstruerer bildeelementet - og deretter legger vi til det genererte bildeelementet til .bilder
uordnet liste.
Husk: ikke bekymre deg om repaints eller reflows.
PhotosView.el
har ikke blitt injisert i DOM ennå.
photosView.el.parentNode // null
Så la oss legge alt sammen!
// Lag en samling av fotomodeller. var photos = nye bilder ([src: 'image1.jpg', 'description': 'Vacation 2012', src: 'image2.jpg', 'description': 'Min beste venn', src: ' image3.jpg ',' description ':' jubileumsfest ']); // Opprett en ny PhotosView, og send inn bildene samlingen var photosView = new PhotosView (collection: photos); // Kast vår liste over bilder i DOM. . $ ( 'Body') html (photosView.el);
Dette kan virke forvirrende først, men det blir sikkert lettere jo mer du jobber med ryggraden. I forrige kodestykke begynner vi ved å lage en samling av Bilde
modeller. Deretter oppretter vi en ny forekomst av PhotosView
container. Når visningen filtreres gjennom alle elementene i den respektive samlingen, oppretter den nye Imageview
forekomster, og legger de resulterende elementene til den uordnede listen. Til slutt tar vi det resulterende DOM-fragmentet og kaster det inn i DOM. Ikke for tøff, ay? Og se: struktur!
Vi har knapt skrapt overflaten av det Backbone er i stand til. For å fortsette læring, se følgende bøker, screencasts og opplæringsprogrammer.
Ryggrad er noen ganger kritisert for ikke å tilby nok. Det håndhever ikke noen bestemt struktur, og det gir ikke UI-komponenter som du kanskje mottar fra Dojo eller jQuery UI. Ironisk nok, til tross for disse kritikkene, er dette det som gjør Backbone så fantastisk. Den håndhever ikke sine meninger til deg. Det gjør en jobb, og en jobb vakkert: gi struktur for dine applikasjoner. Du er da fri til å finne ut hvordan du best passer Backbone i dine eksisterende prosjekter.