Gebruik Backbone.js om interacties te versnellen

Schrijver: Monica Porter
Datum Van Creatie: 13 Maart 2021
Updatedatum: 15 Kunnen 2024
Anonim
ZEITGEIST: MOVING FORWARD | OFFICIAL RELEASE | 2011
Video: ZEITGEIST: MOVING FORWARD | OFFICIAL RELEASE | 2011

Inhoud

Als u snel een kleine JavaScript-tool wilt bouwen, denkt u er waarschijnlijk niet aan om een ​​framework te gebruiken. Makkelijker om wat jQuery-code samen te hacken in plaats van een nieuw framework te installeren en te leren, toch? Fout, Backbone.js is een super lichtgewicht lijmraamwerk dat er net zo uitziet als het gewone oude JavaScript dat je gewend bent te schrijven.

We doen hier bij ZURB veel statische prototypes, omdat we graag door pagina's kunnen klikken zonder back-endcode te hoeven schrijven. Vaak lieten we saaie grijze plaatsaanduidingen zien, of soms gingen we op Flickr zoeken naar voorbeeldafbeeldingen om ons te helpen visualiseren wat er in het uiteindelijke concept zou kunnen gebeuren. Dat is tot een magische vrijdag, toen we besloten dat het geweldig zou zijn om wat JavaScript te schrijven om onze problemen op te lossen. We wilden foto's op Flickr kunnen zoeken en selecteren, rechtstreeks vanuit de placeholder-afbeeldingen zelf. We zouden het FlickrBomb noemen, en dit is het verhaal van hoe we het hebben gebouwd met Backbone.js.


Het wordt ten zeerste aanbevolen om FlickrBomb even te bekijken voordat u gaat lezen. Het is een van die deals van het type 'een klik zegt meer dan duizend woorden'. Ga je gang, we wachten.

Er zijn tegenwoordig veel JavaScript-frameworks in de buurt, SproutCore, JavaScriptMVC, Spine, Sammy, Knockout. Maar we vonden Backbone.js leuk voor dit specifieke project om een ​​paar verschillende redenen:

1. Het is licht (eigenlijk 100% vetvrij)

  • in gewicht, met de nieuwste verpakte versie van ongeveer 4,6 kb
  • in code, met iets meer dan 1000 regels code, is het niet erg moeilijk om een ​​stacktracering tot in de interne onderdelen te volgen zonder je verstand te verliezen

2. Het lijkt op JavaScript

  • omdat het JavaScript is, dat is het en dat is alles
  • het maakt gebruik van jQuery, wat zelfs je oma tegenwoordig kent

3. Supereenvoudig doorzettingsvermogen


  • out-of-the-box bewaart het gegevens naar een backend (via REST), maar door een enkele plug-in te plaatsen, worden in plaats daarvan opgeslagen naar lokale opslag
  • omdat het de persistentie-API abstraheert, kunnen we ervoor zorgen dat het blijft bestaan ​​in een REST-backend door gewoon de plug-in voor lokale opslag te verwijderen

Laten we dan beginnen

Omdat Backbone.js gewoon JavaScript is, hoeven we het alleen samen met Underscore.js op de pagina op te nemen. jQuery is niet per se een harde afhankelijkheid voor Backbone, maar we gaan het gebruiken, dus we zullen het hier opnemen. We koppelen ook de plug-in voor lokale opslag, omdat we geen gedoe willen hebben met het opzetten van een backend. Merk op dat de bestanden hier voor de eenvoud rechtstreeks aan elkaar werden gekoppeld, maar u moet altijd uw eigen middelen in productie hosten.

script src = "http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"> / script> script src = "http://documentcloud.github.com/backbone/ backbone-min.js "> / script> script src =" http://documentcloud.github.com/underscore/underscore-min.js "> / script> script src =" https://raw.github.com/ jeromegn / Backbone.localStorage / master / backbone.localStorage-min.js "> / script>

Alle volgende code in dit artikel is specifiek voor onze applicatie, dus we kunnen deze opnemen in een app.js-bestand, of gewoon inline als dat jouw ding is. Vergeet niet om het op te nemen na Backbone. Backbone maakt het mogelijk om delen van onze applicatie te abstraheren, om ze zowel modulair te maken voor gemakkelijk hergebruik en beter leesbaar voor anderen. Om die abstractie het beste te illustreren, gingen we het ontwerp van FlickrBomb van onderaf uitleggen, te beginnen met de modellen en eindigend met de weergaven.


Ons eerste model

De eerste taak die we moesten aanpakken, is het ophalen van de foto's van Flickr. Het modelleren van een FlickrImage in backbone is eenvoudig genoeg, we zullen een nieuw model maken met de naam FlickrImage en enkele methoden toevoegen om ons te helpen duimen van verschillende grootte te krijgen.

var FlickrImage = Backbone.Model.extend ({fullsize_url: function () {return this.image_url ('medium');}, thumb_url: function () {return this.image_url ('square');}, image_url: function ( size) {var size_code; switch (size) {case 'square': size_code = '_s'; break; // 75x75 case 'medium': size_code = '_z'; break; // 640 op de langste zijkant case 'large ': size_code =' _b '; break; // 1024 aan de langste zijde default: size_code =' ';} return "http: // farm" + this.get (' farm ') + ".static.flickr.com / "+ this.get ('server') +" / "+ this.get ('id') +" _ "+ this.get ('geheim') + size_code +" .webp ";}})

Modellen in Backbone zijn objecten die kunnen worden behouden en waaraan een aantal functies is gekoppeld, net als modellen in andere MVC-frameworks. Het magische deel van Backbone-modellen is dat we gebeurtenissen aan attributen kunnen binden, zodat wanneer dat attribuut verandert, we onze opvattingen kunnen bijwerken om dat weer te geven. Maar we lopen een beetje voor op onszelf.

Als we de foto's van Flickr halen, krijgen we genoeg informatie om URL's voor alle formaten te maken. Die assembly wordt echter aan ons overgelaten, dus hebben we de functie .image_url () geïmplementeerd die een parameter size neemt en een publieke link retourneert. Omdat dit een backbone-model is, kunnen we this.get () gebruiken om toegang te krijgen tot attributen op het model. Met dit model kunnen we dus elders in de code het volgende doen om de URL van een Flickr-afbeelding op te halen.

flickrImage.image_url (’groot’)

Vrij beknopt, hè? Omdat dit model specifiek is voor onze applicatie, zullen we enkele wrapper-functies toevoegen voor de afbeeldingsformaten op volledig formaat en duim.

Een verzameling afbeeldingen

FlickrBomb behandelt verzamelingen afbeeldingen, geen afzonderlijke afbeeldingen, en Backbone heeft een handige manier om dit te modelleren. De toepasselijk genaamde verzameling is wat we zullen gebruiken om Flickr-afbeeldingen samen te groeperen voor een enkele tijdelijke aanduiding.

var FlickrImages = Backbone.Collection.extend ({model: FlickrImage, key: flickrbombAPIkey, pagina: 1, fetch: function (keywords, success) {var self = this; success = success || $ .noop; this.keywords = keywords || this.keywords; $ .ajax ({url: 'http://api.flickr.com/services/rest/', data: {api_key: self.key, format: 'json', method: 'flickr. photos.search ', tags: this.keywords, per_page: 9, page: this.page, license: flickrbombLicenseTypes}, dataType:' jsonp ', jsonp:' jsoncallback ', success: function (response) {self.add (response .photos.photo); success ();}});}, nextPage: function (callback) {this.page + = 1; this.remove (this.models); this.fetch (null, callback);}, prevPage: function (callback) {if (this.page> 1) {this.page - = 1;} this.remove (this.models); this.fetch (null, callback);}});

Er zijn een paar dingen om op te merken. Ten eerste, de model- attribuut vertelt de collecties welk type model het verzamelt. We hebben ook enkele attributen die we hebben geïnitialiseerd voor later gebruik: sleutel is onze Flickr API-sleutel, u wilt flickrbombAPIkey vervangen door de string van uw eigen Flickr API-sleutel. Het verkrijgen van een Flickr API-sleutel is gratis en eenvoudig, volg gewoon deze link: www.flickr.com/services/api/misc.api_keys.html. Het paginakenmerk is de huidige pagina met Flickr-foto's waarop we ons bevinden.

De grote methode hier is .fetch (), die de details van het ophalen van foto's uit de Flickr-API abstraheert. Om problemen met interdomeinverzoeken te voorkomen, gebruiken we JSONP, dat zowel door de Flickr API als door jQuery wordt ondersteund. De andere parameters die we aan de API doorgeven, zouden voor zichzelf moeten spreken. Van bijzonder belang zijn de Backbone-functies die hier worden aangeroepen. In de succes callback gebruiken we .add (), een functie die een reeks modelattributen gebruikt, modelinstances maakt van die attributen en ze vervolgens aan de verzameling toevoegt.

De .nextPage () en .prevPage () functies veranderen eerst de pagina die we willen weergeven,
gebruik de verzamelfunctie .remove (), om alle bestaande modellen uit het
collectie, en roep vervolgens fetch aan om de foto's voor de huidige pagina op te halen (dat we zojuist
gewijzigd).

De FlickrBombImage

Terwijl we weer omhoog werken, hebben we nog een model nodig om de tijdelijke aanduiding voor de afbeelding weer te geven, die zal bestaan ​​uit een verzameling FlickrImages en de huidige FlickrImage die is geselecteerd. We zullen dit model de FlickrBombImage noemen.

var localStorage = (supports_local_storage ())? new Store ("flickrBombImages"): null; var FlickrBombImage = Backbone.Model.extend ({localStorage: localStorage, initialiseren: function () {_.bindAll (this, 'loadFirstImage'); this.flickrImages = nieuwe FlickrImages (); this.flickrImages.fetch (this.get ('keywords'), this.loadFirstImage); this.set (id: this.get ("id")); this.bind ('change: src', this.changeSrc) ;}, changeSrc: function () {this.save ();}, loadFirstImage: function () {if (this.get ('src') === niet gedefinieerd) {this.set ({src: this.flickrImages. eerste (). image_url ()});}}});

Aangezien dit model verantwoordelijk is voor het bijhouden van de momenteel geselecteerde afbeelding tussen het laden van de pagina, moet het weten welke lokale opslagopslag moet worden gebruikt.De eerste regel zorgt ervoor dat er ondersteuning is voor lokale opslag en maakt vervolgens de winkel die we zullen gebruiken om de geselecteerde afbeelding te behouden.

Met Backbone kunnen we een .initialize () -functie definiëren die wordt aangeroepen wanneer een instantie van het model wordt gemaakt. We gebruiken deze functie in FlickrBombImage om een ​​nieuw exemplaar van de FlickrImages-collectie te maken, de trefwoorden door te geven die voor deze afbeelding zullen worden gebruikt en vervolgens de afbeeldingen van Flickr op te halen.

De .loadFirstImage () -functie is doorgegeven als een callback om uit te voeren wanneer de afbeeldingen zijn geladen vanaf Flickr. Zoals u waarschijnlijk wel kunt raden, stelt deze functie de huidige afbeelding in als de eerste in de verzameling van Flickr. Dit gebeurt niet als de huidige afbeelding al is ingesteld.

We gaan ook de attribuut-callbacks van Backbone gebruiken om onze .changeSrc () -functie te activeren wanneer het src-attribuut van dit model verandert. Het enige dat deze callback doet, is het aanroepen van .save (), een Backbone-modelfunctie die de attributen van het model vasthoudt aan elke winkellaag die is geïmplementeerd (in ons geval localstore). Op deze manier blijft de geselecteerde afbeelding onmiddellijk behouden wanneer deze wordt gewijzigd.

De weergavelaag

Nu we alle backend (nou ja, frontend backend) code hebben geschreven, kunnen we de views samenstellen. Weergaven in Backbone zijn een beetje anders dan weergaven in andere traditionele MVC-frameworks. Hoewel een weergave zich doorgaans alleen bezighoudt met presentatie, is een backbone-weergave ook verantwoordelijk voor gedrag. Dat betekent dat uw weergave niet alleen bepaalt hoe iets eruitziet, maar ook wat het moet doen als er interactie mee is.

Een weergave is gewoonlijk (maar niet altijd) gekoppeld aan bepaalde gegevens en doorloopt drie fasen om op basis van die gegevens presentatiemarkeringen te genereren:

1. Het View-object wordt geïnitialiseerd en er wordt een leeg element gemaakt.
2. De renderfunctie wordt aangeroepen en genereert de opmaak voor de weergave door deze in te voegen in het element dat in de vorige stap is gemaakt.
3. Het element is bevestigd aan de DOM.

Dit lijkt misschien veel werk om wat markeringen te genereren, en we zijn nog niet eens bij het gedragsgedeelte van de weergave, maar het is belangrijk, en dit is waarom. Elke keer dat u elementen in de DOM wijzigt, activeert u iets dat een browser reflow wordt genoemd. Een reflow is de browser die herberekent hoe alles op de pagina is gepositioneerd. Browser-reflows kunnen slecht zijn voor de prestaties als ze worden aangeroepen binnen een gebeurtenis voor slepen of vergroten / verkleinen, die met een zeer kort interval wordt geactiveerd, maar erger nog, ze zien er slordig uit. Met complexe paginamanipulatie kunt u daadwerkelijk zien dat elementen aan de pagina worden toegevoegd en dat de betreffende elementen opnieuw worden gepositioneerd. Door het patroon van initialiseren, renderen en bijvoegen van Backbone te volgen, garandeer je een enkele reflow, en de wijzigingen aan de pagina zullen perceptief ogenblikkelijk zijn, ongeacht de complexiteit van elementmanipulatie.

Het FlickrBombImageView

var FlickrBombImageView = Backbone.View.extend ({tagName: "div", className: "flickrbombContainer", lock: false, template: _.template ('div id = "% = this.image.id.replace (" ", "")%> "... / div> '), initialize: function (options) {_.bindAll (this,' addImage ',' updateSrc ',' setDimentions ',' updateDimentions '); var keywords = options. img.attr ('src') .replace ('flickr: //', ''); this. $ el = $ (this.el); this.image = nieuwe FlickrBombImage ({keywords: keywords, id: options. img.attr ('id')}); this.image.flickrImages.bind ('add', this.addImage); this.image.bind ('change: src', this.updateSrc);}, gebeurtenissen: { "click .setupIcon": "clickSetup", "klik .flickrbombFlyout a.photo": "selectImage", "click .flickrbombFlyout a.next": "nextFlickrPhotos", "klik .flickrbombFlyout a.prev": "prevFlickrPhotos"}, render: function () {$ (this.el) .html (this.template ()); this.image.fetch (); this.resize (); return this;}, ...});

De functies van deze weergave zijn weggelaten voor de beknoptheid, de broncode in zijn geheel is beschikbaar op GitHub: github.com/zurb/flickrbomb

Bovenaan de weergave hebben we een aantal backbone-specifieke attributen. tagName en className worden gebruikt om de tag en klasse te definiëren die worden toegepast op het element van deze weergave. Onthoud dat de eerste stap van het maken van een view het maken van een object is, en aangezien die creatie wordt afgehandeld door Backbone, moeten we het element en de klasse specificeren. Merk op dat Backbone verstandige standaardinstellingen heeft; als we deze attributen weglaten, wordt standaard een div gebruikt en wordt er geen klasse toegepast, tenzij u er een opgeeft.

Het sjabloonattribuut is een afspraak, maar niet vereist. We gebruiken het hier om de JavaScript-sjabloonfunctie te specificeren die we zullen gebruiken om onze markeringen voor deze weergave te genereren. We gebruiken de _.template () -functie die is opgenomen in Underscore.js, maar je kunt elke template-engine gebruiken die je verkiest, we zullen je niet beoordelen.

In onze .initialize () -functie halen we de sleutelwoordenreeks uit de afbeeldingstag en maken we vervolgens een FlickrBombImage-model met die sleutelwoorden. We binden ook de functie .addImage () die moet worden uitgevoerd wanneer een FlickrImage wordt toegevoegd aan de FlickrImages-collectie. Deze functie voegt de nieuw toegevoegde FlickrImage toe aan onze vervolgkeuzelijst voor beeldselectie. De laatste en belangrijkste regel is het binden van de .updateSrc () -functie om te activeren wanneer de momenteel geselecteerde FlickrImage wordt gewijzigd. Wanneer de huidige afbeelding in het model wordt gewijzigd, wordt deze functie uitgevoerd, wordt het src-attribuut van het afbeeldingselement bijgewerkt en wordt het formaat van de afbeelding gewijzigd en de afbeelding bijgesneden zodat deze past binnen de afbeeldingsafmetingen die door de gebruiker zijn opgegeven.

events: {"click .setupIcon": "clickSetup", "click .flickrbombFlyout a.photo": "selectImage", "klik .flickrbombFlyout a.next": "nextFlickrPhotos", "klik .flickrbombFlyout a.prev": "prevFlickrPhotos "}

Na .initialize () hebben we het gedragsgedeelte van de weergave. Backbone biedt een gemakkelijke manier om gebeurtenissen te binden met behulp van een gebeurtenisobject. Het events-object gebruikt de jQuery .delegate () - methode om de daadwerkelijke binding aan het View-element uit te voeren, zodat ongeacht welke manipulatie je doet aan het element in de view, al je gebonden events nog steeds zullen werken. Het werkt net als jQuery .live (), behalve dat u in plaats van gebeurtenissen aan het hele document te binden, ze kunt binden binnen het bereik van elk element. De sleutel van elk item in het events-object bestaat uit de event en selector, de waarde geeft die functie aan die aan die event gebonden moet zijn. Merk op dat .delegate () niet werkt met sommige evenementen zoals submit, zie de jQuery .live () documentatie voor een volledige lijst van ondersteunde evenementen.

render: function () {$ (this.el) .html (this.template ()); this.image.fetch (); this.resize (); retourneer dit;}

Ten slotte hebben we de .render () -functie die verantwoordelijk is voor het maken van onze opmaak en het doen van extra werk dat pas kan worden uitgevoerd als de weergave-opmaak is toegevoegd aan het weergave-element. Nadat we onze sjabloon hebben weergegeven, moeten we .fetch () aanroepen op onze FlickrBombImage. .fetch () is een backbone-functie die de laatste kopie van het model uit de persistentielaag haalt. Als we dit model eerder hadden opgeslagen, zou .fetch () die gegevens nu ophalen. Nadat de afbeelding is opgehaald, moeten we resize aanroepen om deze correct te positioneren.

De Home Stretch

Nu alle onderdelen op hun plaats zijn, hoeven we alleen nog maar de plaatsaanduidingsafbeeldingen op de pagina te zoeken en deze te vervangen door de weergegeven FlickrBombImage-weergaven.

$ ("img [src ^ = 'flickr: //']") .each (function () {var img = $ (this), flickrBombImageView = nieuwe FlickrBombImageView ({img: img}); img.replaceWith (flickrBombImageView. render (). el);});

Dit kleine fragment moet onder aan de pagina worden uitgevoerd, of in een document dat klaar is om terug te bellen, om ervoor te zorgen dat het de tijdelijke aanduiding-afbeeldingen kan vinden die het zal vervangen. We gebruiken de conventie van het specificeren van flickr: // [KEYWORD] in het src-attribuut van een afbeeldingstag om aan te geven dat deze gevuld moet worden met afbeeldingen van Flickr. We vinden afbeeldingselementen met een overeenkomend src-attribuut, maken een nieuwe FlickrBombImageView en vervangen de afbeelding vervolgens door de onze. We pakken een kopie van de originele afbeelding en geven deze door aan onze FlickrBombView, zodat we enkele aanvullende configuratie-opties kunnen ophalen die mogelijk op het element zijn gespecificeerd.

Het eindresultaat van al dat harde werk is een heel eenvoudige API voor mensen die de bibliotheek gebruiken. Ze kunnen eenvoudig afbeeldingstags definiëren met behulp van de flickr: // -conventie, de FlickrBomb-code onder aan hun pagina plaatsen en bam, ze hebben tijdelijke aanduidingen voor afbeeldingen van Flickr.

Werkt ook prima met grote oude web-apps

We hebben een grote oude web-app genaamd Notable, die is geschreven zonder zorgen voor het genereren van inhoud aan de clientzijde. Toen we delen van de app turboladen wilden maken door content aan de clientzijde te genereren, kozen we voor Backbone. De redenen waren dezelfde: we wilden een lichtgewicht raamwerk om de code georganiseerd te houden, maar ons niet te dwingen om de hele applicatie te heroverwegen.

We hebben de veranderingen eerder dit jaar met groot succes gelanceerd en sindsdien hebben we Backbones geprezen.

Aanvullende bronnen

Er is veel meer aan Backbone dan wat ik in dit artikel heb behandeld, het C (controller) gedeelte van MVC (model view controller) om te beginnen, wat eigenlijk een R (router) is in de nieuwste versie. En het komt allemaal aan bod in de Backbone-documentatie, een lichte zaterdagochtend te lezen:
documentcloud.github.com/backbone/

Als meer traditionele tutorials jouw ding zijn, bekijk dan de zeer goed gedocumenteerde code van deze todo-applicatie geschreven in Backbone:
documentcloud.github.com/backbone/docs/todos.html

Onze Keus