Aufgrund der zunehmenden Komplexität von JavaScript-Anwendungen sind Frameworks ein absolutes Muss, wenn Sie reale Fristen einhalten müssen. In diesem Artikel werfen wir einen Blick auf ein neues Framework namens Spine Mobile, mit dem Sie fantastische mobile Anwendungen in CoffeeScript und HTML erstellen können, ohne die großartige Benutzererfahrung nativer Apps zu beeinträchtigen.
Interessiert? Lass uns anfangen!
Spine ist ein leichtes JavaScript MVC-Framework, mit dem Sie fantastische clientseitige Webanwendungen erstellen können. Spine Mobile ist eine Erweiterung von Spine, die speziell für die Erstellung nativer Mobile Web-Anwendungen entwickelt wurde.
Aufgabenlisten und Kontaktmanager sind ein Dutzend, also lassen Sie uns in diesem Tutorial etwas anderes machen und einen Trainingsrecorder erstellen. Benutzer werden in der Lage sein, Workouts mit Art, Zeit und Dauer aufzuzeichnen. Dann haben wir eine einfache Liste mit allen aufgezeichneten Workouts. Es gibt auch viel Spielraum für die weitere Entwicklung, z. B. soziale Merkmale und Grafiken.
Sie können hier eine Live-Demo der fertigen Anwendung sowie den gesamten Quellcode des Beispiels auf GitHub abrufen. Es wird dringend empfohlen, dass Sie dieses Tutorial zumindest anfangs mit dem Quellcode befolgen, da es Ihnen hilft, den Einstieg zu erleichtern, wenn Sie mit Spine noch nicht vertraut sind.
Wenn Sie weitere Informationen zu Spine Mobile benötigen, rufen Sie die umfassenden Dokumente oder die Mailingliste auf. Für eine kurze Einführung in CoffeeScript werfen Sie einen Blick auf The Little Book on CoffeeScript.
Zuerst müssen wir einige npm-Module installieren, nämlich Wirbelsäule.app
und Saum
. Ersteres erzeugt Spine-Apps, während letzterer als Abhängigkeitsmanager fungiert. Wenn Sie sie noch nicht installiert haben, müssen Sie Node und npm herunterladen (beide Standorte verfügen über ausgezeichnete Installationsanleitungen). Dann renne:
npm install -g spine.app rand
Um jetzt unsere Spine Mobile-Anwendung zu generieren:
spine mobile spine.workout cd spine.workout
Durchsuchen Sie die Verzeichnisstruktur und die ursprünglichen Dateien, die Spine für Sie erstellt hat.
$ ls -la .gitignore Procfile-Anwendung css package.json public slug.json
Das App
In diesem Verzeichnis befindet sich die gesamte Logik der Anwendung, z. B. Modelle und Controller. Das Öffentlichkeit
Das Verzeichnis ist nur voller statischer Assets, und dazu wird unsere Anwendung letztendlich kompiliert. Es ist das Öffentlichkeit
Verzeichnis, das als mobile Anwendung bereitgestellt wird.
Unsere neue Anwendung hat auch einige lokale Abhängigkeiten (in angegeben package.json
), also lasst uns die jetzt installieren:
npm installieren .
Diese laden und installieren die lokalen Abhängigkeiten in einem Ordner namens Knotenmodule
(was nicht in Ihrer Quellcodeverwaltung sein sollte).
Das letzte, was wir tun müssen, ist, den Entwicklungsserver von Spine, Hem, zu betreiben.
Saum Server
Hem kompiliert CoffeeScript-Dateien, löst Abhängigkeiten auf, bindet die Quelle in CommonJS-Module und verkettet alles in einer JavaScript-Datei,
application.js
.
Nun, da der Server läuft, können wir unter http: // localhost: 9294 zu unserer ursprünglichen Anwendung navigieren.
In MVC-Frameworks speichern Modelle die Daten Ihrer Anwendung und die mit diesen Daten verbundene Logik. Das ist es - Modelle sollten nichts anderes über den Rest Ihrer Anwendung wissen. Sie sollten vollständig entkoppelt sein.
Unsere Anwendung muss das Training verfolgen, die Art des Trainings aufzeichnen, wie lange es gedauert hat und wann es stattgefunden hat.
Lassen Sie uns also ein neues Modell erstellen, indem Sie Folgendes ausführen:
Wirbelsäulenmodell Training
Das erzeugt ein Modell mit dem Namen: app / models / workout.coffee
. Lassen Sie uns diese Datei öffnen und unsere implementieren Trainieren
Modell durch Ersetzen des Inhalts durch Folgendes:
Spine = required ('spine') - Klasse Workout erweitert Spine.Model @configure 'Workout', 'Typ', 'Minuten', 'Datum' @extend Spine.Model.Local load: -> super @date = neues Datum (Datum .parse (@date)) validate: -> return 'type required', es sei denn @type return 'minutes required', sofern nicht @minutes 'date required' zurückgegeben wird, es sei denn @date module.exports = Workout
Ok, das ist eine Menge Code ohne Erklärung. Lassen Sie uns näher darauf eingehen und die Details betrachten.
Zunächst einmal erstellen wir eine Trainieren
Klasse erbt von Wirbelsäule.Modell
, Berufung @konfigurieren()
um den Namen und die Attribute des Modells festzulegen:
Klasse Workout erweitert Spine.Model @configure 'Workout', 'Typ', 'Minuten', 'Datum'
So weit, ist es gut. Jetzt erweitern wir das Modell um ein Modul mit dem Namen Spine.Model.Local
. Dadurch wird sichergestellt, dass die Modelldaten zwischen dem erneuten Laden der Seite mit dem lokalen HTML5-Speicher erhalten bleiben.
@extend Spine.Model.Local
Nun die nächste Funktion, Belastung()
, braucht eine kleine Erklärung. Belastung()
wird intern mehrfach in Spine aufgerufen, insbesondere wenn Datensätze serialisiert und deserialisiert werden. Unser Problem ist, dass wir die Datensätze in JSON serialisieren, wenn Sie sie mit HTML5 Local Storage beibehalten. JSON hat jedoch keinen nativen 'Date'-Typ und serialisiert ihn nur in einen String. Dies ist ein Problem, wie wir wollen Datum
Attribut, immer ein JavaScript-Datum zu sein. Überschreiben Belastung()
, Stellen Sie sicher, dass das Datumsattribut ein JavaScript ist Datum
, wird dieses Problem lösen.
load: -> super @date = neues Datum (Date.parse (@date))
Schließlich haben wir eine ziemlich unkomplizierte bestätigen()
Funktion. In Spine schlägt die Validierung eines Modells fehl, wenn die bestätigen()
Die Funktion gibt etwas "wahr" zurück - d. h. eine Zeichenfolge. Hier kommen wir zurück "Typ erforderlich"
es sei denn, die Art
Attribut ist vorhanden. Mit anderen Worten, wir bestätigen die Anwesenheit von Art
, Protokoll
und Datum
Attribute.
validate: -> return 'type required', es sei denn @type return 'minutes required', sofern nicht @minutes 'date required' zurückgegeben wird, sofern nicht @date
Sie werden feststellen, dass die letzte Zeile im Modell a ist modul.exporte
Zuordnung. Dies macht das sichtbar Trainieren
Klasse, so dass andere Dateien es erfordern können. Wirbelsäulenanwendungen verwenden CommonJS-Module, für die explizite Modulanforderungen und der Export von Eigenschaften erforderlich sind.
Das einzige andere Modell, das wir brauchen, ist a WorkoutType
Modell. Dies wird nur eine grundlegende Klasse sein und enthält eine Liste gültiger Trainingstypen. Wie zuvor müssen wir zuerst das Modell generieren:
Wirbelsäulenmodell Workout_type
Und dann ist der Inhalt eine einfache Klasse, die ein Array gültiger Trainingstypen enthält:
Klasse WorkoutType @types: ['Laufen "Joggen" Gehen "Schwimmen" Tennis "Squash" Handstand "Überspringen" Aerobic "Biken" Gewichte "] @all: -> @types module.exports = WorkoutType
Weitere Informationen zu Modellen finden Sie im Handbuch zu den Spine-Modellen.
In Spine-Anwendungen sind Controller die Verbindung zwischen Modellen und Ansichten. Sie fügen der Ansicht Ereignis-Listener hinzu, ziehen Daten aus dem Modell und rendern JavaScript-Vorlagen.
Das Wichtigste, was Sie über Spines Controller wissen müssen, ist, dass sie alle von einem einzigen Element, dem el
Eigentum. Alles, was ein Controller zu Lebzeiten macht, wird von diesem Element bestimmt. ob es darum geht, Ereignis-Listener hinzuzufügen, auf Ereignisrückrufe zu reagieren, den HTML-Code des Elements zu aktualisieren oder Formulardaten abzurufen.
Spine Mobile-Anwendungen haben eine globale Bühne
Controller, der den gesamten Bildschirm umfasst. Unsere generierte Anwendung enthält bereits eine Bühne
im app / index.coffee
, Lassen Sie uns es durch Folgendes ersetzen:
Requires ('lib / setup') Spine = Requires ('Spine') Stage = Requires ('Spine.mobile') Workouts = Requires ('Controller / Workouts') Klasse App erweitert Stage.Global-Konstruktor: -> super # Instanziieren Sie unseren Workouts-Controller mit neuen Workouts. # Richten Sie Route-Spine.Route.setup (shim: true) ein. @Navigate '/ workouts' module.exports = App
Unsere App
Die Bühne wird der erste Controller sein, der instanziiert wird, und der Rest der Anwendung wird eingerichtet. Sie sehen, es ist ein undefinierter Controller mit dem Namen erforderlich Workouts
, und instantiierend Workouts
in der Klasse' Konstrukteur
Funktion.
Mit anderen Worten, wenn unsere Anwendung zum ersten Mal ausgeführt wird, wird die App
Die Bühne wird instanziiert. Das wird unsererseits instanziieren Workouts
Controller, wo die ganze Aktion sein wird. Sie können das gesamte Routenmaterial vorerst ignorieren.
Nun lass uns das oben genannte einrichten Workouts
Regler:
Wirbelsäulen-Controller-Workouts
Das neue Workouts
Controller befindet sich unter App / Controller / Workouts.Coffee
. Dieser Controller befindet sich an dem Ort, an dem sich die meisten unserer Anwendungen befinden. Füllen Sie ihn aus, indem Sie den Inhalt durch Folgendes ersetzen:
Spine = required ('spine') Panel = required ('spine.mobile') # Erfordert Modelle Workout = required ('models / workout') WorkoutType = required ('models / workout_type') # Zu implementieren: Klasse WorkoutsList erweitert die Panel-Klasse WorkoutsCreate erweitert die Panel-Klasse Workouts erweitert den Spine.Controller-Konstruktor: -> super # Die beiden Panels unserer Anwendung @list = new WorkoutsList @create = new WorkoutsCreate # Richten Sie einige Route-Stuff @routes '/ workouts' ein: (params) -> @ list.active (params) '/ workouts / create': (params) -> @ create.active (params) # Ruft die anfänglichen Workouts aus dem lokalen Speicher ab Workout.fetch () module.exports = Workouts
Lassen Sie uns noch einmal näher darauf eingehen und erklären, was los ist. Erstens benötigen wir zwei Modelle unserer Anwendung, Trainieren
und WorkoutType
:
# Requires models Workout = required ('models / workout') WorkoutType = required ('models / workout_type')
Dann Workouts
Konstruktor baut einige auf Panel
s, noch nicht implementiert, und dann einige Routen, die wir vorerst ignorieren können. Endlich, Workout.fetch ()
aufgerufen wird, um alle gespeicherten Daten aus dem lokalen Speicher abzurufen.
Ok, jetzt haben wir uns ziemlich gut mit unserem zusammengetan App
und Workouts
Controller, aber jetzt kommt der lustige Teil, die Panels.
Unsere Anwendung hat also zwei Panel
Controller, eine Listenansicht und eine Erstellungsansicht. Diese beiden Panels gehören zur Hauptbühne, wodurch sichergestellt wird, dass sie richtig ein- und ausgehen, wobei jeweils nur ein Panel angezeigt wird.
Also definieren wir zuerst unser Trainingsliste
Controller in App / Controller / Workouts.Coffee
, Sie haben es erraten, werden die Trainingseinheiten auflisten. Fügen Sie den folgenden Code nach dem hinzu benötigen
Aussagen in Workouts.Coffee
, Vor dem Workouts
Controller-Definition:
Klasse WorkoutsList erweitert Panel-Titel: Konstruktor 'Workouts': -> super # Fügt eine Schaltfläche zum Header hinzu @addButton ('Add', @add) # Binden Sie das Modell an die Ansicht Workout.bind ('Refresh Change', @render). render: => # Holt alle Trainingsdatensätze aus den Modell-Workouts = Workout.all () # Rendert eine Vorlage mit dem Trainingsarray template = required ('views / workouts') (workouts) # Ersetzen Sie den HTML-Code des aktuellen Elements durch die Vorlage @. html (template) add: -> # Navigiere zum 'create' -Controller mit einem # swipe-Übergang nach links @navigate ('/ workouts / create', trans: 'right')
Das erste, was Sie bemerken werden, ist das Trainingsliste
erweitert Panel
, eine in der Klasse definierte Klasse spine.mobile
Paket. Dies stellt sicher, dass es erbt Panel
Eigenschaften, so die Anwendung Bühne
kann damit arbeiten.
Die Vorlage verwendet eine große Bibliothek namens Eco. Weitere Informationen zur Syntax finden Sie im View-Handbuch. Es genügt zu sagen, es ist die CoffeeScript-Syntax mit der
Notation zum Rendern von Vorlagenvariablen auf der Seite.
Dann haben wir eine Eigenschaft genannt Titel
. Dies ist eine optionale Einstellung und ist der Titel unseres Panels.
In der Konstruktorfunktion fügen wir dem Panel-Header durch Aufrufen eine Schaltfläche hinzu @addButton (Titel, Rückruf)
. Wenn Sie darauf tippen, wird die Klasse aufgerufen. hinzufügen()
Funktion.
Zuletzt fügen wir zwei Events eine Bindung hinzu, Aktualisierung und Veränderung auf der Trainieren
Modell. Bei jeder Änderung des Modells werden diese Ereignisse und unser Rückruf ausgelöst machen()
Funktion aufgerufen. machen()
Zuerst zieht alles aus Trainieren
Datensätze aus der Datenbank, rendert dann eine Vorlage und ersetzt den Inhalt des Panels durch das Ergebnis.
Diese Vorlage wirkt also nur als Funktion. Alles, was wir tun, ist die Ausführung dieser Funktion, indem wir einen Vorlagenkontext übergeben. Das Ergebnis ist das gerenderte DOM-Element. Weitere Informationen zur Funktionsweise finden Sie im Ansichtenhandbuch. Andernfalls drücken Sie auf und definieren die Vorlage.
Im App / Ansichten
, Erstellen Sie einen Ordner namens Workouts
die alle unsere Vorlagen enthält Workouts
Regler. Dann erstellen wir eine Datei unter app / views / workouts / index.jeco
enthaltend:
<%= @type %> zum <%= @minutes %> min auf <%= @date.toDateString() %>
Die Vorlage ist .jeco
Die Erweiterung ist kein Tippfehler, sondern eine jQuery-Erweiterung der von Hem bereitgestellten Eco-Vorlagenbibliothek. Es ermöglicht uns unter anderem, Elemente mit den ursprünglichen Vorlagendaten zu verknüpfen, was später nützlich sein wird.
Das Endergebnis ist eine Liste von Workouts, die folgendermaßen aussehen:
Wenn Sie keine Workouts erstellt haben, ist die Liste offensichtlich leer. Wir können ein Training programmatisch erstellen, indem Sie die Befehlszeile in der Web Inspector-Konsole verwenden:
var Workout = erfordern ('Modelle / Workout'); Workout.create (Typ: 'Handstand'), Minuten: 5, Datum: Date.now ());
Jetzt ist das letzte zu definierende Panel WorkoutsCreate
, Dieses enthält das Formular zum Erstellen neuer Workouts. Dies wird unser größter Controller sein, aber es sollte recht einfach sein, sobald Sie mit der API und der Terminologie vertraut sind.
Der einzige Neuzugang hier ist der Zusatz eines Elemente
Diese Eigenschaft ist ein Hilfsmittel, mit dem DOM-Elemente Instanzvariablen zugeordnet werden können. In dem folgenden Beispiel ist die Elementeigenschaft auf festgelegt 'form': 'form'
, welche karten die
Element zum
@bilden
Variable.
Klasse WorkoutsCreate erweitert Panel-Titel: "Add Workout" -Elemente: "form": "form" -Konstruktor: -> super @addButton ('Back', @back) @addButton ('Create', @create) # Rendern Sie immer die Ansicht Panel ist aktiviert, # setzt das Formular zurück @bind 'active', @render () Rendern: -> # Alle Trainingstypen abrufen types = WorkoutType.all () # Rendern Sie die Vorlage und ersetzen Sie die HTML @html-Anforderung ('Ansichten / Workouts) / form ') (types: types) create: -> # Neues Workout aus Formulardaten erstellen = Workout.create (@formData ()) # Navigieren Sie zurück zur Liste, wenn die Validierung @back () bestanden hat, wenn item # Navigiert zurück Zur Liste zurück: -> @ form.blur () @navigate ('/ workouts', trans: 'left') # Formulardaten als Objektliteral abrufen formData: -> type = @ form.find ('[name = type] '). val () minutes = parseInt (@ form.find (' [name = Minuten] '). val ()) date = @ form.find (' [name = date] ') [0] .valueAsDate Typ: Typ, Minuten: Minuten, Datum: Datum
Nehmen wir das Stück für Stück auseinander. Erstens in der WorkoutsCreate
Konstruktor fügen wir dem Panel zwei Schaltflächen hinzu: 'Erstellen' und 'Zurück'. Sie können wahrscheinlich erraten, was diese tun werden.
Als Nächstes binden wir uns an das Panel aktiv Ereignis, das ausgelöst wird, wenn das Panel angezeigt wird. Wenn das Ereignis ausgelöst wird, wird die machen()
Funktion wird aufgerufen, wobei der HTML-Code des Controller-Elements durch eine gerenderte Vorlage ersetzt wird. Durch Anbringen der machen()
Aufruf an die aktiv Wenn nicht direkt im Konstruktor, stellen wir sicher, dass das Formular zurückgesetzt wird, wenn das Panel aufgerufen wird.
Der letzte Teil des Panels ist der erstellen()
Funktion, wo unser Trainieren
Rekord wird tatsächlich erstellt. Wir benutzen Formulardaten()
um die Eingaben des Benutzers abzurufen, übergeben Sie diese an Workout.create ()
.
Nun zur Definition der app / views / workouts / form.eco
Vorlage in der machen()
Funktion:
Das war es für unsere Anwendung. Machen Sie einen Wirbel, und erstellen Sie ein paar Trainingseinheiten.
Der letzte Schritt besteht darin, unsere Anwendung auf der Festplatte zu erstellen und sie bereitzustellen. Wir können das mit Hem tun:
Saum bauen
Dadurch werden alle Ihre JavaScript / CoffeeScript-Dateien in eine Datei serialisiert (public / application.js
) und alle Ihre CSS / Stylus (public / application.css
). Sie müssen dies tun, bevor Sie Ihre Site auf einen Remote-Server übertragen, damit sie statisch bereitgestellt werden kann.
Wir werden Heroku für unsere Anwendung verwenden, eine großartige Option für die Bereitstellung von Node.js- und Rails-Anwendungen, und sie haben einen großzügigen kostenlosen Plan. Wenn Sie noch keinen haben, müssen Sie sich für ein Konto bei ihnen anmelden und den Heroku-Edelstein installieren.
Jetzt müssen Sie nur noch ein paar Heroku-Befehle ausführen, um unsere App bereitzustellen.
heroku meine spine-app erstellen --stack cedar git add. git commit -m "first commit" git drücken heroku master heroku auf
Voila! Sie haben jetzt eine mobile Anwendung, die in CoffeeScript, HTML5 und CSS3 geschrieben wurde. Wir haben jetzt unzählige Möglichkeiten, beispielsweise PhoneGap einzubinden, um auf die APIs des Telefons zuzugreifen, das Design für Android-Telefone anzupassen oder Offline-Unterstützung hinzuzufügen.
Es mag sich nach vielem Lernen anfühlen, aber in diesem Tutorial haben wir die meisten API von Spines behandelt. Schauen Sie sich die umfangreiche Dokumentation an und erfahren Sie mehr über das Framework?
Ich bin sicher, dass Sie viele Fragen haben, also zögern Sie nicht, in den Kommentaren nachzufragen, und vielen Dank für das Lesen! Ansonsten finden Sie auf unserer Schwesterseite Mobiletuts + die besten Mobile-orientierten Tutorials im Web!