Débuter avec Spine Mobile

Compte tenu de la complexité croissante des applications JavaScript, les frameworks sont un impératif absolu si vous devez respecter les délais réels. Dans cet article, nous allons examiner un nouveau cadre appelé Spine Mobile, que vous pouvez utiliser pour créer des applications mobiles impressionnantes en CoffeeScript et HTML, sans sacrifier la grande expérience utilisateur des applications natives..

Intéressé? Commençons!


Qu'est-ce que l'épine??

Spine est un framework JavaScript MVC léger que vous pouvez utiliser pour créer d’impressionnantes applications Web côté client. Spine Mobile est une extension de Spine spécialement conçue pour la création d'applications Web mobiles à sensation native..

Les listes de tâches et les gestionnaires de contacts ne coûtent qu’une douzaine de points, alors faisons quelque chose de différent dans ce tutoriel et créons un enregistreur d’entraînement. Les utilisateurs vont pouvoir enregistrer des séances d'entraînement, y compris leur type, l'heure et la durée. Ensuite, nous allons avoir une simple liste montrant tous les entraînements enregistrés. Il existe également de nombreuses possibilités de développement, telles que des fonctionnalités sociales et des graphiques..

Vous pouvez commander une démonstration en direct de l'application terminée ici, ainsi que tout le code source de l'exemple sur GitHub. Je vous recommande vivement de suivre ce didacticiel en utilisant le code source, du moins au début, car il vous aidera à démarrer si vous débutez dans Spine..

Si vous avez besoin de plus de détails sur Spine Mobile, consultez la documentation complète ou la liste de diffusion. Pour une brève introduction à CoffeeScript, jetez un coup d’œil à The Little Book on CoffeeScript.


Étape 1: Configuration

Tout d’abord, nous devons installer des modules npm, à savoir: spine.app et ourlet. Le premier génère des applications Spine, tandis que le second agit en tant que gestionnaire de dépendance. Si vous ne les avez pas déjà installés, vous devrez télécharger Node et npm (les deux sites disposent d'excellents guides d'installation). Puis lancez:

npm installer -g spine.app our

Maintenant, pour générer réellement notre application Spine Mobile:

colonne vertébrale mobile spine.workout cd spine.workout

Parcourez la structure de répertoires et les fichiers initiaux créés par Spine pour vous..

$ ls -la .gitignore Procfile app css package.json public slug.json

le app Le répertoire est le lieu où réside toute la logique de l'application, tels que ses modèles et ses contrôleurs. le Publique répertoire est juste plein d’actifs statiques, et c’est là que notre application sera finalement compilée. C'est le Publique répertoire qui est servi comme notre application mobile.

Notre nouvelle application a aussi des dépendances locales (spécifiées dans package.json), alors allons-y et installons-les maintenant:

npm installer .

Ceux-ci téléchargeront et installeront les dépendances locales dans un dossier appelé node_modules (qui ne devrait pas être dans votre contrôle de source).

La dernière chose à faire est d’exécuter le serveur de développement de Spine, Hem..

serveur ourlet

Hem compile les fichiers CoffeeScript, résout les dépendances, encapsule la source dans des modules CommonJS et concatène le tout dans un fichier JavaScript., application.js.

Maintenant que le serveur est en cours d'exécution, nous pouvons accéder à notre application initiale sur http: // localhost: 9294..


Étape 2: Modèles

Dans les frameworks MVC, les modèles stockent les données de votre application, ainsi que toute logique associée à ces données. C'est tout - les modèles ne devraient rien savoir d'autre sur le reste de votre application; ils devraient être complètement découplés.

Notre application doit suivre les entraînements, enregistrer le type d’entraînement, sa durée et la date à laquelle il s’est déroulé..

Alors allons-y et créons un nouveau modèle en lançant ce qui suit:

modèle de colonne vertébrale

Cela va générer un modèle nommé: app / models / workout.coffee. Ouvrons ce fichier et mettons en œuvre notre Faire des exercices modèle en remplaçant le contenu par ceci:

Spine = require ('spine') class workout étend Spine.Model @configure 'workout', 'type', 'minutes', 'date' @extend Spine.Model.Local charge: -> super @date = new Date (Date .parse (@date)) validate: -> return 'type required', sauf si @type return 'minutes est nécessaire', sauf si @minutes return 'date est requise', sauf si @date module.exports = Workout

Ok, ça fait beaucoup de code sans aucune explication; approfondissons et regardons les détails.

Tout d'abord, nous créons un Faire des exercices classe héritant de Spine.Model, appel @configure () pour définir le nom et les attributs du modèle:

classe Workout étend Spine.Model @configure 'Workout', 'type', 'minutes', 'date'

Jusqu'ici tout va bien. Nous allons maintenant étendre le modèle avec un module nommé Spine.Model.Local. Cela garantit la persistance des données de modèle entre les recharges de page à l'aide du stockage local HTML5..

@extend Spine.Model.Local

Maintenant la fonction suivante, charge(), a besoin d'un peu d'explication. charge() est appelé plusieurs fois en interne dans Spine, en particulier lorsque les enregistrements sont sérialisés et désérialisés. Notre problème est que nous sérialisons les enregistrements en JSON lorsque nous les persistons avec le stockage local HTML5. Cependant, JSON n'a pas de type "Date" natif et le sérialise simplement en chaîne. Ceci est un problème, comme nous voulons rendez-vous amoureux attribuer à toujours être une date JavaScript. Primordial charge(), en s'assurant que l'attribut de date est un JavaScript Rendez-vous amoureux, va résoudre ce problème.

load: -> super @date = new Date (Date.parse (@date))

Enfin, nous avons un assez simple valider() une fonction. Dans Spine, la validation d’un modèle échoue si le valider() function renvoie n'importe quoi 'vérité' - c'est-à-dire une chaîne. Ici nous revenons "type requis" à moins que le type attribut existe. En d'autres termes, nous validons la présence du type, minutes et rendez-vous amoureux les attributs.

valider: -> return 'type required' à moins que @type return 'minutes nécessaires' à moins que @minutes return 'date requise' à moins que @date

Vous remarquerez que la dernière ligne du modèle est un module.exports affectation. Cela expose le Faire des exercices classe, donc d’autres fichiers peuvent en avoir besoin. Les applications Spine utilisent des modules CommonJS, ce qui nécessite des modules explicites et une exportation de propriété..

Modèle WorkoutType

Le seul autre modèle dont nous aurons besoin est un Type d'entraînement modèle. Cela va juste être une classe de base, et contient une liste de types d'entraînement valides. Comme auparavant, nous devons d'abord générer le modèle:

modèle de colonne vertébrale workout_type

Et puis son contenu est une classe simple, contenant un tableau de types d’entraînement valides:

class WorkoutType @types: ['running "jogging" marche "natation", tennis, squash "repose-mains" sautant "aérobic" vélo "poids"] @all: -> @types module.exports = WorkoutType

Pour plus d'informations sur les modèles, veuillez consulter le guide des modèles Spine..


Étape 3: contrôleurs principaux

Dans les applications Spine, les contrôleurs sont le liant entre les modèles et les vues. Ils ajoutent des écouteurs d'événements à la vue, extraient des données du modèle et rendent des modèles JavaScript..

La chose essentielle à savoir sur les contrôleurs Spine, c’est qu’ils sont tous liés par un seul élément, le el propriété. Tout ce qu'un contrôleur fait dans sa vie est limité par cet élément; qu'il s'agisse d'ajouter des écouteurs d'événements, de répondre aux rappels d'événements, de mettre à jour le code HTML de l'élément ou d'extraire des données de formulaire.

Applications Spine Mobile ont un global Étape contrôleur, qui englobe la totalité de l'écran. Notre application générée comprend déjà un Étape dans app / index.coffee, remplaçons-le par ce qui suit:

require ('lib / setup') Spine = require ('spine') Stage = require ('spine.mobile') Workouts = require ('contrôleurs / entraînements') La classe App étend le constructeur Stage.Global: -> super # Instanciez notre contrôleur d'entraînement de nouvelles séances d'entraînement # Configurez quelques trucs de route Spine.Route.setup (shim: true) @navigate '/ workouts' module.exports = App

Notre App Stage va être le premier contrôleur instancié et en charge de la configuration du reste de l'application. Vous pouvez voir, cela nécessite un contrôleur non encore défini nommé Séances d'entraînement, et instanciant Séances d'entraînement dans la classe' constructeur une fonction.

En d’autres termes, lors de la première utilisation de notre application, la App l'étape va être instanciée. Cela instanciera à notre tour Séances d'entraînement contrôleur, où toute l'action va être. Vous pouvez ignorer tous les trucs de la route pour le moment.

Maintenant, configurons ce qui précède Séances d'entraînement manette:

séances d'entraînement de contrôleur d'épine

Le nouveau Séances d'entraînement le contrôleur est situé sous app / controllers / workouts.coffee. Ce contrôleur sera l’endroit où réside la plupart de nos applications. Nous allons donc commencer par le remplir en remplaçant son contenu par ce qui suit:

Spine = require ('spine') Panneau = require ('spine.mobile') # Exiger des modèles Workout = require ('models / workout') WorkoutType = require ('models / workout_type') # À implémenter: class WorkoutsList étend la classe Panel WorkoutsCreate étend la classe Panel Workouts étend le constructeur Spine.Controller: -> super # les deux panneaux de notre application @list = new WorkoutsList @create = new WorkoutsCreate # Configurez quelques trucs d'itinéraire @routes '/ workouts': (paramètres) -> @ list.active (params) '/ workouts / create': (params) -> @ create.active (params) # Récupère les entraînements initiaux dans le stockage local Workout.fetch () module.exports = Entraînements

Encore une fois, approfondissons cela et expliquons ce qui se passe. Tout d'abord, nous avons besoin des deux modèles de notre application, Faire des exercices et Type d'entraînement:

# Require modèles Workout = require ('models / workout') WorkoutType = require ('models / workout_type')

ensuite Séances d'entraînement constructeur met en place quelques Panneaus, pas encore implémenté, puis quelques routes que nous pouvons ignorer pour le moment. finalement, Workout.fetch () est appelé, récupérant toutes les données stockées de la mémoire locale.


Étape 4: Liste des séances d'entraînement

Ok, maintenant nous avons fait pas mal de préparation avec notre App et Séances d'entraînement contrôleurs, mais vient maintenant la partie amusante, les panneaux.

Donc, notre application a deux Panneau des contrôleurs, une vue liste et une vue créer. Ces deux panneaux appartiennent à la scène principale, ce qui garantit leur transition en entrant et en sortant correctement et en affichant un seul panneau à la fois..

Alors définissons d'abord notre Liste d'entrainements contrôleur dans app / controllers / workouts.coffee, qui, vous l’avez deviné, listera les séances d’entraînement. Ajoutez le code suivant après le exiger déclarations dans séances d'entraînement.café, avant le Séances d'entraînement définition du contrôleur:

class WorkoutsList étend le titre du panneau: constructeur 'Workouts': -> super # Ajoute un bouton à l'en-tête @addButton ('Add', @add) # Lie le modèle à la vue Workout.bind ('refresh change', @render) render: => # Récupère tous les enregistrements d'entraînement du modèle workouts = Workout.all () # Rend un modèle avec le tableau d'entraînement template = require ('views / workouts') (workouts) # Remplace le code HTML de l'élément actuel par le modèle @ html (template) add: -> # Naviguez vers le contrôleur 'create', avec une transition # de balayage vers la gauche @navigate ('/ workouts / create', trans: 'right')

La première chose que vous remarquerez est que Liste d'entrainements s'étend Panneau, une classe définie dans le colonne vertébrale paquet. Cela garantit qu'il hérite Panneaupropriétés de, donc l'application de Étape peut travailler avec elle.

Le modèle utilise une excellente bibliothèque appelée Eco. Consultez le guide d'affichage pour plus d'informations sur sa syntaxe. Autant dire que c’est la syntaxe CoffeeScript, en utilisant le notation pour rendre les variables de modèle à la page.

Ensuite, nous avons une propriété appelée Titre. Ceci est un paramètre optionnel, et sera le titre de notre panel.

Dans la fonction constructeur, nous ajoutons un bouton à l'en-tête du panneau en appelant @addButton (titre, rappel). Lorsque vous appuyez sur cette option, la classe ' ajouter() une fonction.

Enfin, nous ajoutons une liaison à deux événements, rafraîchir et changement sur le Faire des exercices modèle. Chaque fois que le modèle est modifié, ces événements sont déclenchés et notre rappel rendre() fonction invoquée. rendre() commence par sortir tous les Faire des exercices enregistrements de la base de données, puis restitue un modèle en remplaçant le contenu du panneau par le résultat.

Donc, ce modèle agit simplement comme une fonction. Nous ne faisons qu'exécuter cette fonction en transmettant un contexte de modèle, le résultat étant l'élément DOM rendu. Pour plus d'informations sur son fonctionnement, reportez-vous au guide des vues. Sinon, appuyons sur et définissons le modèle..

Dans app / vues, créer un dossier appelé séances d'entraînement qui contiendra tous nos modèles associés à la Séances d'entraînement manette. Ensuite, créons un fichier sous app / views / workouts / index.jeco contenant:

 
<%= @type %> pour <%= @minutes %> minutes sur <%= @date.toDateString() %>

Le modèle .Jeco L'extension n'est pas une faute de frappe, c'est une extension jQuery de la bibliothèque de modèles Eco fournie par Hem. Entre autres choses, cela nous permet d’associer des éléments aux données du modèle original, ce qui sera utile plus tard..

Le résultat final est une liste d'entraînements ressemblant à ceci:

De toute évidence, si vous n'avez pas créé d'entraînement, la liste sera vide. Nous pouvons créer un entraînement par programme, en utilisant la ligne de commande dans la console Web Inspector:

var Workout = require ('models / workout'); Workout.create (type: 'handstands', minutes: 5, date: date.now ());

Étape 5: Créer de nouvelles séances d'entraînement

Maintenant, le dernier panneau à définir est EntraînementsCréer, qui contiendra le formulaire pour créer de nouvelles séances d'entraînement. Ce sera notre plus grand contrôleur, mais cela devrait être assez simple, maintenant que vous connaissez l’API et la terminologie..

La seule nouveauté ici est l’ajout d’un éléments property, qui est une aide de commodité pour faire correspondre les éléments DOM aux variables d'instance. Dans l'exemple ci-dessous, la propriété elements est définie sur 'formulaire': 'formulaire', qui cartographie le
élément du @forme variable.

class WorkoutsCreate étend le titre du panneau: éléments 'Add Workout': constructeur 'form': 'form': -> super @addButton ('Back', @back) @addButton ('Create', @create) # Rend la vue à chaque fois le panneau est activé, # réinitialisant le formulaire @bind 'actif', @render () rendu: -> # Récupère tous les types d’entraînement types = WorkoutType.all () # Rend le modèle en remplaçant le code HTML @html require ('vues / entraînements / form ') (types: types) crée: -> # Crée un nouvel entraînement à partir d'un élément de données de formulaire = Workout.create (@formData ()) # Retourne à la liste, si la validation est passée @back () si élément # retourne à la liste retour à la liste: -> @ form.blur () @navigate ('/ workouts', trans: 'left') # Récupère les données de formulaire en tant qu’objet littéral formData: -> type = @ form.find ('[name = type] '). val () minutes = parseInt (@ form.find (' [nom = minutes] '). val ()) date = @ form.find (' [nom = date] ') [0] .valueAsDate type: type, minutes: minutes, date: date

Alors prenons cette pièce par pièce. Tout d'abord, dans le EntraînementsCréer constructeur, nous ajoutons deux boutons au panneau, "Créer" et "Retour". Vous pouvez probablement deviner ce qu'ils vont faire.

Ensuite, nous lions au panneau actif événement, déclenché chaque fois que le panneau est affiché. Lorsque l'événement est déclenché, le rendre() La fonction est appelée, en remplaçant le code HTML de l'élément du contrôleur par un modèle de rendu. En attachant le rendre() invocation à la actif événement, plutôt que directement dans le constructeur, nous nous assurons que le formulaire est réinitialisé chaque fois que vous accédez au panneau.

La dernière partie du panneau est la créer() fonction, où notre Faire des exercices enregistrement va effectivement être créé. Nous utilisons Données de formulaire() pour récupérer la saisie de l'utilisateur, en la passant à Workout.create ().

Maintenant sur la définition de la app / views / workouts / form.eco modèle utilisé dans le rendre() une fonction:

Voilà pour notre application. Faites un tourbillon et créez quelques séances d'entraînement.


Étape 6: Construire et déployer

La dernière étape consiste à créer notre application sur disque et à la déployer. Nous pouvons le faire en utilisant Hem:

ourlet

Cela sérialisera tout votre JavaScript / CoffeeScript dans un fichier (public / application.js) et tous vos CSS / Stylus (public / application.css). Vous devez le faire avant de transférer votre site sur un serveur distant afin qu'il puisse être servi de manière statique..

Nous allons utiliser Heroku pour servir notre application, une excellente option pour servir les applications Node.js et Rails, et ils ont un plan gratuit généreux. Vous devrez créer un compte avec eux si vous n'en avez pas déjà, et installer le joyau Heroku..

Maintenant, tout ce dont nous avons besoin pour déployer notre application est de lancer quelques commandes Heroku pour que notre application soit déployée..

Heroku créer mon-spine-app - pile de cèdre git ajouter. git commit -m "premier commit" git push maître heroku heroku ouvert

Voila! Vous avez maintenant une application mobile astucieuse écrite en CoffeeScript, HTML5 et CSS3. Nous avons maintenant une multitude de possibilités, telles qu'emballer PhoneGap pour accéder aux API du téléphone, personnaliser le thème pour les téléphones Android ou ajouter une prise en charge hors ligne..


Prochaines étapes

Cela peut sembler beaucoup à apprendre, mais nous avons en fait couvert la plupart des API de Spine dans ce tutoriel. Pourquoi ne pas consulter la documentation détaillée et en apprendre un peu plus sur le cadre?

Je suis sûr que vous avez beaucoup de questions, n'hésitez donc pas à les demander et merci beaucoup de votre lecture! Sinon, assurez-vous de consulter notre site soeur, Mobiletuts +, pour les meilleurs tutoriels sur le Web destinés aux mobiles.!