Użyj Backbone.js, aby przyspieszyć interakcje

Autor: Monica Porter
Data Utworzenia: 13 Marsz 2021
Data Aktualizacji: 15 Móc 2024
Anonim
Scaling Backbone.js at SoundCloud
Wideo: Scaling Backbone.js at SoundCloud

Zawartość

Jeśli chcesz szybko stworzyć małe narzędzie JavaScript, prawdopodobnie nie myślisz o używaniu frameworka. Łatwiej jest zhakować trochę kodu jQuery zamiast instalować i uczyć się nowego frameworka, prawda? Źle, Backbone.js to super lekki framework do klejenia, który wygląda tak, jak zwykły stary JavaScript, do którego jesteś przyzwyczajony.

W ZURB tworzymy wiele statycznych prototypów, ponieważ lubimy mieć możliwość przeglądania stron bez konieczności pisania kodu zaplecza. Często wrzucaliśmy szare, zastępcze obrazy lub czasami przeszukiwaliśmy Flickr w poszukiwaniu przykładowych obrazów, aby pomóc nam zwizualizować, co może się znaleźć w ostatecznej wersji roboczej. Tak było do pewnego magicznego piątku, kiedy zdecydowaliśmy, że byłoby wspaniale napisać trochę JavaScript, aby rozwiązać nasze problemy. Chcieliśmy mieć możliwość wyszukiwania i wybierania zdjęć w serwisie Flickr bezpośrednio z samych obrazów zastępczych. Nazwalibyśmy to FlickrBomb, a to jest historia tego, jak zbudowaliśmy go przy użyciu Backbone.js.


Zdecydowanie zalecamy szybkie zapoznanie się z FlickrBomb przed przeczytaniem. To jedna z umów typu „kliknięcie jest warte tysiąca słów”. Śmiało, poczekamy.

Obecnie w bloku jest wiele frameworków JavaScript, SproutCore, JavaScriptMVC, Spine, Sammy, Knockout. Ale spodobał nam się Backbone.js w tym konkretnym projekcie z kilku różnych powodów:

1. Jest lekki (w rzeczywistości w 100% beztłuszczowy)

  • pod względem wagi, przy czym najnowsza zapakowana wersja ma około 4,6 kb
  • w kodzie, ponieważ zawiera nieco ponad 1000 wierszy kodu, nie jest strasznie trudno prześledzić stos stosu do elementów wewnętrznych, nie tracąc zmysłów

2. Wygląda jak JavaScript

  • ponieważ to jest JavaScript, to wszystko
  • używa jQuery, które zna nawet Twoja babcia

3. Super prosta wytrwałość


  • po wyjęciu z pudełka zachowuje dane w zapleczu (przez REST), ale upuszczając pojedynczą wtyczkę, zamiast tego zapisuje w pamięci lokalnej
  • ponieważ wyodrębnia interfejs API trwałości, moglibyśmy go utrwalić w zapleczu REST, po prostu usuwając lokalną wtyczkę magazynu

Zacznijmy więc

Ponieważ Backbone.js to tylko JavaScript, wszystko, co musimy zrobić, to umieścić go na stronie wraz z plikiem Underscore.js. jQuery nie jest trudną zależnością dla Backbone per se, ale zamierzamy go używać, więc uwzględnimy go tutaj. Połączymy również lokalną wtyczkę pamięci masowej, ponieważ nie chcemy kłopotać się konfigurowaniem zaplecza. Zwróć uwagę, że pliki były tutaj bezpośrednio łączone dla uproszczenia, ale zawsze powinieneś przechowywać własne zasoby w środowisku produkcyjnym.

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>

Cały poniższy kod w tym artykule jest specyficzny dla naszej aplikacji, więc możemy go umieścić w pliku app.js lub po prostu wbudować, jeśli to lubisz. Pamiętaj tylko, aby umieścić go po Backbone. Backbone pozwala wyodrębnić fragmenty naszej aplikacji, aby były zarówno modułowe, aby można je było łatwo ponownie wykorzystać, jak i bardziej czytelne dla innych. Aby najlepiej zilustrować tę abstrakcję, zamierzam wyjaśnić projekt FlickrBomb od podstaw, zaczynając od modeli, a kończąc na widokach.


Nasz pierwszy model

Pierwszym zadaniem, z jakim mieliśmy się zmierzyć, jest pobranie zdjęć z Flickr. Modelowanie FlickrImage w sieci szkieletowej jest dość proste, utworzymy nowy model o nazwie FlickrImage i dodamy kilka metod, które pomogą nam uzyskać kciuki o różnych rozmiarach.

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; // case 75x75 'medium': size_code = '_z'; break; // 640 na najdłuższym przypadku bocznym 'large ': size_code =' _b '; break; // 1024 na najdłuższej stronie domyślnie: size_code =' ';} return "http: // farm" + this.get (' farm ') + ".static.flickr.com / "+ this.get ('server') +" / "+ this.get ('id') +" _ "+ this.get ('secret') + size_code +" .webp ";}})

Modele w Backbone to obiekty, które mogą być utrwalane i mają pewne powiązane z nimi funkcje, podobnie jak modele w innych frameworkach MVC. Magiczna część modeli Backbone polega na tym, że możemy wiązać zdarzenia z atrybutami, tak że gdy ten atrybut się zmieni, możemy zaktualizować nasze widoki, aby to odzwierciedlić. Ale trochę się wyprzedzamy.

Kiedy pobierzemy zdjęcia z Flickr, uzyskamy wystarczającą ilość informacji, aby utworzyć adresy URL dla wszystkich rozmiarów. Jednak ten zestaw jest pozostawiony nam, więc zaimplementowaliśmy funkcję .image_url (), która przyjmuje parametr size i zwraca łącze publiczne. Ponieważ jest to model szkieletowy, możemy użyć this.get (), aby uzyskać dostęp do atrybutów w modelu. W tym modelu możemy wykonać następujące czynności w innym miejscu kodu, aby uzyskać adres URL obrazu Flickr.

flickrImage.image_url („duży”)

Całkiem zwięzłe, co? Ponieważ ten model jest specyficzny dla naszej aplikacji, dodamy kilka funkcji opakowania dla pełnowymiarowych i miniaturowych rozmiarów obrazu.

Zbiór zdjęć

FlickrBomb zajmuje się kolekcjami obrazów, a nie pojedynczymi obrazami, a Backbone ma wygodny sposób modelowania tego. Trafnie nazwana Kolekcja jest tym, czego użyjemy do zgrupowania obrazów Flickr dla jednego symbolu zastępczego.

var FlickrImages = Backbone.Collection.extend ({model: FlickrImage, key: flickrbombAPIkey, page: 1, fetch: function (words, success) {var self = this; success = success || $ .noop; this.keywords = słowa kluczowe || this.keywords; $ .ajax ({url: 'http://api.flickr.com/services/rest/', data: {api_key: self.key, format: 'json', metoda: '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);}});

Należy tu zwrócić uwagę na kilka rzeczy. Po pierwsze, plik Model atrybut informuje kolekcje, jaki typ modelu zbiera. Mamy również pewne atrybuty, które zainicjowaliśmy później: klucz to nasz klucz Flickr API, będziesz chciał zastąpić flickrbombAPIkey ciągiem własnego klucza Flickr API. Uzyskanie klucza Flickr API jest bezpłatne i łatwe, wystarczy kliknąć to łącze: www.flickr.com/services/api/misc.api_keys.html. Atrybut strony to bieżąca strona ze zdjęciami Flickr, na których się znajdujemy.

Największą metodą jest tutaj .fetch (), która usuwa szczegóły pobierania zdjęć z Flickr API. Aby uniknąć problemów z żądaniami międzydomenowymi, używamy formatu JSONP, który obsługuje zarówno interfejs Flickr API, jak i jQuery. Pozostałe parametry, które przekazujemy do API, powinny być zrozumiałe. Szczególnie interesujące są tutaj nazywane funkcje Backbone. W wywołaniu zwrotnym sukcesu używamy .add (), funkcji, która pobiera tablicę atrybutów modelu, tworzy instancje modelu z tych atrybutów, a następnie dodaje je do kolekcji.

Funkcje .nextPage () i .prevPage () najpierw zmieniają stronę, którą chcemy wyświetlić,
użyj funkcji kolekcji .remove (), aby usunąć wszystkie istniejące modele z pliku
kolekcji, a następnie zadzwoń do pobierania, aby pobrać zdjęcia z bieżącej strony (po prostu
zmieniony).

Plik FlickrBombImage

Wracając do góry, potrzebujemy jeszcze jednego modelu do reprezentowania obrazu zastępczego, który będzie składał się z kolekcji FlickrImages i bieżącego wybranego FlickrImage. Nazwijmy ten model FlickrBombImage.

var localStorage = (support_local_storage ())? nowy Sklep ("flickrBombImages"): null; var FlickrBombImage = Backbone.Model.extend ({localStorage: localStorage, initialize: function () {_.bindAll (this, 'loadFirstImage'); this.flickrImages = new FlickrImages (); this.flickrImages.fetch (this.get ('words'), this.loadFirstImage); this.set (id: this.get ("id")); this.bind ('change: src', this.changeSrc) ;}, changeSrc: function () {this.save ();}, loadFirstImage: function () {if (this.get ('src') === undefined) {this.set ({src: this.flickrImages. first (). image_url ()});}}});

Ponieważ ten model jest odpowiedzialny za śledzenie aktualnie wybranego obrazu między wczytywaniem strony, musi wiedzieć, jakiego magazynu lokalnego użyć.Pierwsza linia zapewni obsługę lokalnego magazynu, a następnie utworzymy magazyn, którego użyjemy do utrwalenia wybranego obrazu.

Backbone pozwala nam zdefiniować funkcję .initialize (), która zostanie wywołana podczas tworzenia instancji modelu. Używamy tej funkcji w FlickrBombImage, aby utworzyć nową instancję kolekcji FlickrImages, przekazać słowa kluczowe, które będą używane dla tego obrazu, a następnie pobrać obrazy z Flickr.

Funkcja .loadFirstImage () została przekazana jako wywołanie zwrotne do uruchomienia po załadowaniu obrazów z Flickr. Jak można się pewnie domyślić, funkcja ta ustawia bieżący obraz jako pierwszy w kolekcji Flickr. Nie robi tego, jeśli bieżący obraz został już ustawiony.

Zamierzamy również użyć wywołań zwrotnych atrybutów Backbone, aby uruchomić naszą funkcję .changeSrc (), gdy zmieni się atrybut src tego modelu. Wszystko, co robi to wywołanie zwrotne, to wywołanie .save (), funkcji modelu Backbone, która utrwala atrybuty modelu w dowolnej warstwie sklepu, która została zaimplementowana (w naszym przypadku localstore). W ten sposób za każdym razem, gdy wybrany obraz zostanie zmieniony, jest on natychmiast utrwalany.

Warstwa widoku

Teraz, gdy mamy już napisany cały kod zaplecza (cóż, zaplecza frontendowego), możemy zebrać widoki. Widoki w Backbone są nieco inne niż widoki w innych tradycyjnych frameworkach MVC. Podczas gdy widok zwykle dotyczy tylko prezentacji, widok szkieletowy jest również odpowiedzialny za zachowanie. Oznacza to, że Twój widok nie tylko określa, jak coś wygląda, ale także, co powinno robić podczas interakcji.

Widok jest zwykle (ale nie zawsze) powiązany z niektórymi danymi i przechodzi przez trzy fazy, aby wygenerować znaczniki prezentacji na podstawie tych danych:

1. Obiekt View jest inicjalizowany i tworzony jest pusty element.
2. Wywoływana jest funkcja renderowania, która generuje znaczniki dla widoku przez wstawienie go do elementu utworzonego w poprzednim kroku.
3. Element jest przymocowany do DOM.

Może się wydawać, że generowanie pewnych znaczników wymaga dużo pracy, a nie jesteśmy jeszcze nawet w części widoku dotyczącej zachowania, ale jest to ważne, a oto dlaczego. Za każdym razem, gdy modyfikujesz elementy, które są w DOM, uruchamiasz coś, co nazywa się ponownym przepływem przeglądarki. Przepływ to przeglądarka obliczająca ponownie pozycję wszystkich elementów na stronie. Ponowne przepływy przeglądarki mogą mieć negatywny wpływ na wydajność, jeśli zostaną wywołane w ramach zdarzenia przeciągania lub zmiany rozmiaru, które uruchamia się w bardzo krótkich odstępach czasu, ale co gorsza, wyglądają niechlujnie. Dzięki złożonej manipulacji na stronie można faktycznie zobaczyć elementy dodawane do strony i elementy, które zmieniają położenie. Podążając za wzorcem inicjalizacji, renderowania i dołączania Backbone, gwarantujesz pojedynczy przepływ, a zmiany na stronie będą natychmiastowe, niezależnie od złożoności manipulacji elementami.

Plik 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 words = options. img.attr ('src') .replace ('flickr: //', ''); this. $ el = $ (this.el); this.image = new FlickrBombImage ({words: keyword, id: options. img.attr ('id')}); this.image.flickrImages.bind ('add', this.addImage); this.image.bind ('change: src', this.updateSrc);}, events: { "click .setupIcon": "clickSetup", "click .flickrbombFlyout a.photo": "selectImage", "click .flickrbombFlyout a.next": "nextFlickrPhotos", "click .flickrbombFlyout a.prev": "prevFlickrPhotos"}, render: function () {$ (this.el) .html (this.template ()); this.image.fetch (); this.resize (); return this;}, ...});

Funkcje tego widoku zostały pominięte dla zwięzłości, kod źródłowy w całości jest dostępny na GitHub: github.com/zurb/flickrbomb

W górnej części widoku mamy kilka specyficznych atrybutów Backbone. tagName i className służą do definiowania znacznika i klasy, które zostaną zastosowane do elementu tego widoku. Pamiętaj, że pierwszym krokiem tworzenia widoku jest utworzenie obiektu, a ponieważ to tworzenie jest obsługiwane przez Backbone, musimy określić element i klasę. Zauważ, że Backbone ma rozsądne wartości domyślne; jeśli pominiemy te atrybuty, domyślnie używany jest element div i żadna klasa nie zostanie zastosowana, chyba że ją określisz.

Atrybut szablonu jest konwencją, ale nie jest wymagany. Używamy go tutaj, aby określić funkcję szablonu JavaScript, której użyjemy do wygenerowania naszych znaczników dla tego widoku. Używamy funkcji _.template () zawartej w Underscore.js, ale możesz użyć dowolnego preferowanego silnika tworzenia szablonów, nie będziemy cię oceniać.

W naszej funkcji .initialize () wyciągamy ciąg słów kluczowych ze znacznika obrazu, a następnie tworzymy model FlickrBombImage przy użyciu tych słów kluczowych. Wiążemy również funkcję .addImage () do uruchomienia, gdy FlickrImage zostanie dodany do kolekcji FlickrImages. Ta funkcja dołączy nowo dodany FlickrImage do naszego menu wysuwanego selektora obrazu. Ostatnia i najważniejsza linia wiąże funkcję .updateSrc () do uruchomienia, gdy aktualnie wybrany FlickrImage zostanie zmieniony. Gdy bieżący obraz zostanie zmieniony w modelu, ta funkcja zostanie uruchomiona, zaktualizuje atrybut src elementu obrazu oraz CSS zmieni rozmiar i przytnij obraz, aby pasował do wymiarów obrazu określonych przez użytkownika.

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

Po .initialize () mamy część dotyczącą zachowania widoku. Backbone zapewnia wygodny sposób wiązania zdarzeń przy użyciu obiektu zdarzeń. Obiekt zdarzeń używa metody jQuery .delegate (), aby wykonać faktyczne powiązanie z elementem View, dzięki czemu niezależnie od tego, jakie manipulacje wykonasz na elemencie wewnątrz widoku, wszystkie powiązane zdarzenia będą nadal działać. Działa podobnie jak jQuery .live (), z tym wyjątkiem, że zamiast wiązać zdarzenia z całym dokumentem, można je wiązać w zakresie dowolnego elementu. Klucz każdego wpisu w obiekcie zdarzeń składa się ze zdarzenia i selektora, wartość wskazuje, że funkcja powinna być powiązana z tym zdarzeniem. Zwróć uwagę, że .delegate () nie działa z niektórymi zdarzeniami, takimi jak submit, zobacz dokumentację jQuery .live (), aby uzyskać pełną listę obsługiwanych zdarzeń.

render: function () {$ (this.el) .html (this.template ()); this.image.fetch (); this.resize (); zwróć to;}

Na koniec mamy funkcję .render (), która jest odpowiedzialna za tworzenie naszych znaczników i wykonywanie dodatkowej pracy, której nie można wykonać, dopóki znacznik View nie zostanie dodany do elementu View. Po wyrenderowaniu naszego szablonu musimy wywołać .fetch () w naszym FlickrBombImage. .fetch () to funkcja Backbone, która pobiera najnowszą kopię modelu z warstwy trwałości. Gdybyśmy wcześniej zapisali ten model, .fetch () pobrałby te dane teraz. Po pobraniu obrazu musimy wywołać resize, aby ustawić go poprawnie.

Rozciąganie w domu

Gdy wszystkie elementy są już na miejscu, wszystko, co musimy teraz zrobić, to znaleźć obrazy zastępcze na stronie i zastąpić je wyrenderowanymi widokami FlickrBombImage.

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

Ten mały wycinek należy uruchomić na dole strony lub w wywołaniu zwrotnym gotowym do dokumentu, aby upewnić się, że może znaleźć obrazy zastępcze, które zastąpi. Używamy konwencji określania flickr: // [KEYWORD] w atrybucie src tagu obrazu, aby wskazać, że powinien być wypełniony obrazami z Flickr. Znajdujemy elementy obrazu z pasującym atrybutem src, tworzymy nowy FlickrBombImageView, a następnie zastępujemy obraz naszym. Pobieramy kopię oryginalnego obrazu i przekazujemy ją do naszego FlickrBombView, abyśmy mogli pobrać dodatkowe opcje konfiguracyjne, które mogły zostać określone w elemencie.

Efektem końcowym całej tej ciężkiej pracy jest bardzo proste API dla osób korzystających z biblioteki. Mogą po prostu zdefiniować tagi obrazów przy użyciu konwencji flickr: //, upuścić kod FlickrBomb na dole strony i bach, mają obrazy zastępcze z Flickr.

Działa również świetnie z aplikacjami internetowymi Big OL

Mamy wielką, olbrzymią aplikację internetową o nazwie Notable, która została napisana bez troski o generowanie treści po stronie klienta. Kiedy chcieliśmy, aby sekcje aplikacji były ładowane w trybie turbo poprzez generowanie zawartości po stronie klienta, wybraliśmy Backbone. Powody były takie same: chcieliśmy mieć lekki framework, który pomógłby utrzymać porządek w kodzie, ale nie zmuszał nas do ponownego przemyślenia całej aplikacji.

Wprowadziliśmy zmiany na początku tego roku z wielkim sukcesem i od tego czasu śpiewamy pochwały Backbones.

Dodatkowe zasoby

Backbone to o wiele więcej niż to, co omówiłem w tym artykule, część C (kontroler) MVC (kontroler widoku modelu) na początek, która jest w rzeczywistości R (routerem) w najnowszej wersji. Wszystko jest omówione w dokumentacji Backbone, czytamy w lekki sobotni poranek:
documentcloud.github.com/backbone/

Jeśli wolisz bardziej tradycyjne samouczki, zapoznaj się z bardzo dobrze udokumentowanym kodem tej aplikacji do zrobienia, napisanej w Backbone:
documentcloud.github.com/backbone/docs/todos.html

Polecany Dla Ciebie
10 czasopism poświęconych projektowaniu asów do dodania do listy lektur
Czytaj Więcej

10 czasopism poświęconych projektowaniu asów do dodania do listy lektur

Magazyny projektowe mają wiele funkcji: informują o tym, co dzieje ię w branży, in pirują, oferują porady, które może z za to ować do wła nego portfolio projektowego, do tarczają po trzeżeń od up...
Czołowi artyści tworzą 120 niestandardowych psów z papieru
Czytaj Więcej

Czołowi artyści tworzą 120 niestandardowych psów z papieru

Projekty, w których połeczność projektantów gromadzi ię, aby tworzyć coś naprawdę oryginalnego i in pirującego, je t zaw ze pięknym widokiem. Tutaj ponad 100 najbardziej ek cytujących i wpły...
Najlepsze aplikacje VR w 2021 roku
Czytaj Więcej

Najlepsze aplikacje VR w 2021 roku

zuka z najlep zych aplikacji VR? W tym przewodniku omówiono najważniej ze opcje korzy tania z wirtualnej rzeczywi tości na urządzeniu mobilnym i amodzielnego tworzenia rzeczywi tości wirtualnej....