Comme pour toute application Web, la création de sites de plusieurs pages nécessite un ensemble d’outils spécialisés. Dans cet article, nous allons voir comment développer une bibliothèque qui non seulement puisse différencier les différents URI, mais aussi qui exploite les principales fonctionnalités de Meteor..
Chaque fois que je dois développer une bibliothèque spécifique et ciblée comme celle-ci, j'aime commencer par le résultat de, comment puis-je que cela fonctionne?
Nous pouvons donc commencer par écrire certaines des fonctionnalités que nous aimerions avoir:
Cela a l'air bien. Maintenant, après avoir examiné ces fonctionnalités, vous pouvez penser qu'elles ressemblent beaucoup à un type de bibliothèque 'routeur' et je suis d'accord. Voyons donc comment notre bibliothèque 'routeur' fonctionnerait en action:
Router.addRoute ('/ home', 'homeTemplate'); Router.addRoute ('/ utilisateur /: nom d'utilisateur', 'profileTemplate'); Router.addRoute ('/ contact', 'contactTemplate'); Router.run ();
En conception, vous avez des concepts tels que 'forme-suit-fonction', qui utilise l'idée de tout organiser en premier et de le concevoir plus tard.
En code, je trouve souvent que le contraire est plus utile. En tant que développeurs, nous pouvons travailler dans de nombreuses directions et avoir un exemple concret de ce à quoi devrait ressembler la conception nous permet de rester concentrés et efficaces..
Maintenant que je sais ce que je veux faire, il ne reste plus qu'à la mettre en œuvre. Alors, jetons un autre regard sur nos fonctionnalités que nous avons écrites ci-dessus; nous voulons pouvoir ajouter des itinéraires et laisser Meteor rendre le modèle donné partiel. Bien entendu, les vues de Meteor fonctionnent par défaut avec les modèles du guidon, c'est pourquoi j'ai pris la décision d'en faire la dénomination de notre routeur..
Ensuite, divisons le projet en différentes sections afin de connaître les fonctionnalités sur lesquelles nous devons travailler..
window.location.pathname
variable, fournie par le navigateur.addRoute
qui acceptera un modèle de route et un nom de modèle. Cette fonction devra ensuite stocker tous ces objets route dans une sorte de tableau.Si tout va bien, vous pouvez voir qu'en énonçant les exigences, cela aide vraiment à rationaliser la phase de planification. Nous sommes maintenant prêts à intervenir.
Pour commencer, créons un nouveau projet Meteor, je vais nommer le mien 'routeurdemo
'. Maintenant, à l'intérieur, nous allons créer un dossier nommé 'lib
'dans un autre dossier nommé'client
':
météore créer routerdemo cd routerdemo mkdir -p client / lib
Ensuite, créez un fichier nommé 'routeur.js
'à l'intérieur du nouvellement créé lib
dossier. La raison pour laquelle nous la collonsclient
', c’est que le serveur n’a pas accès à la window.location.pathname
variable et en tant que tel, ne fonctionnera pas avec notre routeur. Mettre des choses dans un dossier nommé 'client
'assure qu'ils ne seront exécutés que du côté client.
Maintenant dans le routeur.js
fichier que vous venez de créer, installons un échafaudage:
//////////////////////////// // Routeur /////////////////////// ///// Router = uri: / * URL actuelle * /, routes: [], addRoute: / * fonction pour ajouter une route * /, getMatchingRoute: / * fonction pour obtenir la route correspondante * /, exécutez: / * fonction pour afficher le modèle de l'itinéraire correspondant * /;
Je pense que c'est un très bon échafaudage, j'ai même rempli le code du tableau d'itinéraires et ajouté quelques commentaires (progrès!). Maintenant, pour développer plus avant notre bibliothèque, nous devons discuter de la manière dont nous allons associer ces itinéraires..
Ce n'est pas aussi simple que currentRoute === route
, comme nous avons affaire à des espaces réservés dynamiques. Nous voulons un itinéraire pour '/identifiant d'utilisateur
'faire correspondre l'URI de'/ utilisateur / 42
' etc.
Pour ce faire, nous allons devoir diviser l'URI et faire un peu plus d'analyse en profondeur. Maintenant, certaines personnes pourraient penser à utiliser une regex, mais c'est un peu exagéré si vous me le demandez. Une approche beaucoup plus simple consisterait à diviser les segments et à s’assurer que les deux itinéraires ont le même nombre de segments, et à ce que les parties de l’itinéraire qui ne sont pas des espaces réservés fassent la correspondance..
Ceci peut être facilement réalisé en scindant l’URI partout où il y a une barre oblique ('/'), en utilisant le .Divisé
méthode. Donc, notre première vérification ferait en sorte que les deux itinéraires ont le même nombre de segments.
Si la route est '/identifiant d'utilisateur
'et nous obtenons un URI'/ profil / 42 / foo / bar
', nous n’avons même pas besoin de vérifier davantage, l’un a deux segments et l’autre en a quatre, ce qui semble être un bon contrôle primaire. La prochaine chose que nous pouvons faire est de filtrer les listes et d’assurer la correspondance de chaque élément qui n’est pas un paramètre fictif. Si ces deux vérifications sont vraies, nous savons que la route correspond.
Commençons donc avec le réglage de la uri
variable:
uri: _.compact (window.location.pathname.split ("/")),
Dans le code ci-dessus, nous fractionnons le tableau en barres obliques et transformons la chaîne en un tableau de segments. Ensuite, nous utilisons Underscore compact
Pour supprimer tous les éléments vides de la liste, ceux-ci peuvent être provoqués par une barre oblique au début ou par une personne qui utilise deux barres obliques par erreur. En faisant cela, notre système sera beaucoup plus indulgent.
Ensuite, nous devons créer la fonction pour ajouter une route, il s’agit d’un processus assez similaire, mais comme nous allons faire correspondre les espaces réservés ultérieurement, nous allons stocker non seulement les segments et le nom du modèle, mais aussi les index pour les espaces réservés ainsi.
Voici la fonction terminée:
addRoute: fonction (route, modèle) var segments = _.compact (route.split ("/")); var espaces réservés = _.reduce (segments, fonction (currentArr, pièce, index) if (pièce.substr (0, 1) === ":") currentArr.push (index); segments [index] = pièce. substr (1); return currentArr;, []); this.routes.push (route: segments, template: template, placeholderIndexes: placeholders); ,
Nous commençons par diviser la route en segments, comme nous l'avons fait pour l'URI, mais cette fois-ci, nous devons également stocker les index des espaces réservés pour référence future, en utilisant les caractères Underscore. réduire
méthode.
Pour l'ignorant, le réduire
la fonction est similaire à la chaque
méthode, il passe également en revue tous les éléments d’une liste, à la différence près, il transmet tout ce que chaque itération renvoie à l’élément suivant, pour finalement renvoyer les résultats à la variable donnée. Nous commençons avec un tableau vide (le 3ème paramètre) et nous ajoutons chaque index au fur et à mesure que nous les trouvons et le transmettons jusqu'à ce qu'il soit finalement renvoyé à la liste. espaces réservés
variable.
La prochaine chose que vous verrez ici, c'est que nous renommons les segments qui sont des espaces réservés et supprimons le côlon. Nous le faisons uniquement pour des raisons esthétiques. Par la suite, cela facilitera la référence dans les modèles..
Enfin, nous transmettons les nouvelles données à notre tableau de routes, créé précédemment..
L'étape suivante consiste à filtrer dans la liste et à rechercher un itinéraire correspondant à l'URI actuel..
Voici la fonction complète:
getMatchingRoute: function () for (var i dans this.routes) var route = this.routes [i]; var data = ; if (route.segments.length === this.uri.length) var match = _.every (route.segments, fonction (seg, i) if (_.contains (route.placeholderIndexes, i)) data [seg] = this.uri [i]; return true; else return seg === this.uri [i];, cela); if (match) return data: data, template: route.template // pas de correspondance (ajouter 404 ou template par défaut peut-être?) return false; ,
Nous faisons pas mal de choses ici, alors parcourons-les. Nous commençons par parcourir le tableau d'itinéraires, puis nous affectons l'itinéraire actuel à une variable, ainsi qu'à un objet de données vide pour stocker les espaces réservés..
Ensuite, nous vérifions pour nous assurer que les deux itinéraires ont le même nombre de segments. Sinon, nous passons simplement à l’itinéraire suivant. S'ils ont le même nombre de composants, nous devons vérifier si les segments correspondent, vous pouvez le faire avec Underscore '_.chaque
' une fonction. Cette fonction est encore comme_.chaque
'méthode, sauf qu'il renvoie un booléen. La façon dont cela fonctionne est que la fonction sera exécutée pour chaque élément du tableau. S'ils retournent tous la valeur true, la fonction retournera la valeur true, sinon, elle retournera la valeur false, elle est donc parfaite pour effectuer des opérations comme celle-ci, où nous devons vérifier chaque segment..
Maintenant, le contrôle que nous effectuons est assez facile, si c'est un espace réservé, alors il convient automatiquement, puisqu'un espace réservé peut être égal à n'importe quelle valeur. Si ce n'est pas un espace réservé, nous nous assurons simplement que les deux segments correspondent, assez simple.
Afin de vérifier s’il s’agit ou non d’un espace réservé, nous passons l’index des segments en cours (stocké dans 'je
') à Underscore _.contient
fonction, qui vérifiera sa valeur.
Maintenant, vous vous demandez peut-être quelle est la première ligne de cette 'si
'instruction est en train de se faire, eh bien, il stocke le segment dans le tableau de données sous le nom d'espace réservé indiqué. Alors, disons par exemple que vous aviez un itinéraire de '/Nom d'utilisateur
'et l'URI actuel est'/ utilisateur / bob
', cette ligne ajoutera une propriété à l'objet de données appelée'prénom
'et passez une valeur de bob
.
Le reste est assez évident, nous passons vrai ou faux, selon les circonstances, et le résultat est stocké dans 'rencontre
'. Si match est true, nous retournons les données avec le nom du modèle, et s'il n'y a pas de correspondance, nous renvoyons false. Et c'est tout pour notre getMatchingRoute
méthode.
Jusqu'à présent, nous pouvons obtenir l'URI actuel, ajouter des itinéraires et trouver un itinéraire correspondant. Il ne reste plus qu'à afficher le bon itinéraire. Pour cela, nous devons écrire le 'courir
' méthode.
Meteor utilise un guidon pour les modèles et stocke tous les modèles dans une variable, nommée de manière appropriée, 'Modèle
'. Maintenant, si vous connaissez le guidon, alors vous savez que ces modèles ne sont que des fonctions, et en les appelant (en leur transmettant éventuellement des données), nous récupérons le code HTML du modèle..
Maintenant, appeler ces fonctions pour obtenir le code HTML du modèle fonctionnerait bien, mais ce n'est pas très semblable à Meteor, car nous en arriverions à un site Web statique normal. Heureusement, l'ajout du comportement dynamique est plus facile que vous ne le pensez, tout ce que nous avons à faire est d'envelopper l'appel de fonction dans un 'Meteor.render
' appel. En le mettant dans cette fonction, il réagira aux changements dans les données et le gardera en direct.
Pour cette raison, l’exécution du routeur est très simple, créons la méthode d’exécution:
run: function () var route = this.getMatchingRoute (); if (route) var fragment = Meteor.render (function () if (Modèle [route.template]!! = = non défini) retour Modèle [route.template] (route.data);); document.body.appendChild (fragment); else // 404
Nous commençons par obtenir l'itinéraire correspondant, en utilisant le getMatchingRoute
fonction que nous venons d'écrire, nous nous assurons alors qu'il y a une correspondance, et finalement nous utilisons un autre
déclaration pour gérer l'affichage d'un 404.
Dans la déclaration if, nous appelons Meteor.render
et à l'intérieur, nous vérifions et appelons le modèle renvoyé, en lui transmettant les données des espaces réservés. Cette fonction retournera un fragment HTML, que nous pourrons ensuite simplement ajouter au corps du document..
Donc, avec environ 60 lignes de code, nous avons terminé notre routeur.
La prochaine étape consiste à le tester. Je vais utiliser le même code que celui que nous avons écrit plus tôt lors de la planification de ce projet, car ce sera une bonne mesure de savoir si nous avons accompli, ce que nous voulions accomplir. Ajoutons un fichier nommé main.js
à l'intérieur de client
dossier et ajouter ce qui suit:
Meteor.startup (function () Router.addRoute ('/ home', 'homeTemplate'); Router.addRoute ('/ utilisateur /: nom d'utilisateur', 'profileTemplate'); Router.addRoute ('/ contact', 'contactTemplate '); Router.run (););
Dans le code ci-dessus, nous devons d’abord nous assurer que nos modèles et notre corps seront disponibles avant d’essayer de travailler avec notre routeur. Nous faisons cela en enveloppant tout notre code à l'intérieur de la Meteor.startup
appel de méthode. Cela garantira que tout est prêt, et à l'intérieur de la Commencez
méthode, nous pouvons ensuite ajouter nos routes et exécuter le routeur.
Créons maintenant quelques modèles, cela peut être fait n’importe où, vous pouvez créer un sous-dossier dans le client
dossier nommé templates et créez un fichier HTML distinct pour chacun, mais comme il s’agit de modèles courts et à titre d’exemple, je vais les regrouper dans un fichier nommé 'templates.html
' à l'intérieur de 'client
'dossier:
Ceci est la page d'accueil
Page de profil
Bienvenue à nouveau nom d'utilisateur
Page de contact
Contactez-moi sur Twitter à l'adresse twitterName
Le premier modèle est assez basique, il contient juste un peu de code HTML pour l'en-tête de la page d'accueil. Le deuxième modèle est très similaire au premier modèle, mais cette fois nous utilisons le Nom d'utilisateur
paramètre de route. Maintenant, le dernier modèle utilise également un espace réservé, mais son itinéraire n'a pas le twitterName
segment. En effet, les espaces réservés standard de Meteor continueront de fonctionner et fonctionneront de manière réactive..
De retour à l'intérieur du client
dossier, créons maintenant un fichier nommé 'templates.js
', pour déclarer l'espace réservé au contact.
Template.contactTemplate.twitterName = function () Session.setDefault ('twitter_name', '@gabrielmanricks'); return Session.get ('twitter_name');
Vous auriez pu simplement renvoyer une chaîne, mais je voulais démontrer que tout est encore réactif. La dernière étape consiste à supprimer les fichiers html et js par défaut du répertoire racine (dans mon cas, ils sont nommés routerdemo.html et routerdemo.js). Ceci fait, démarrez le serveur Meteor et accédez aux routes indiquées..
Essayez d'aller '/maison
' ou 'utilisateur / gmanricks
' ou '/contact
'et ils devraient tous travailler pour vous comme prévu. Une autre chose est que, puisque nous avons stocké le nom Twitter dans Session, nous pouvons simplement ouvrir la console du navigateur sur la page de contact et entrer:
Session.set ('twitter_name', '@nettuts');
Et vous verrez que la page sera mise à jour en temps réel!
Dans cet article, nous avons construit une bibliothèque de routeurs de base, tout en lui apportant une touche Meteor. Nous avons couvert beaucoup de concepts de base et, en fin de compte, beaucoup de concepts Underscore..
En fin de compte, j'espère que j'ai bien compris qu'il n'y a pas de véritable "magie" ici. Il s’agit vraiment de mettre en œuvre ce dont vous avez besoin, par opposition à ce que vous pouvez.
Merci d'avoir lu, j'espère que vous avez apprécié. Comme toujours, si vous avez des questions, vous pouvez les laisser ci-dessous ou me les poser sur le NetRC IRC ou sur Twitter..
Remarque: Si vous souhaitez en savoir plus sur Meteor, je viens de publier mon nouveau livre, qui détaille le processus de création d'une application, de sa conception et sa planification à sa sécurisation et à son déploiement. Vous pouvez prendre le livre au format ebook ainsi que sous couverture souple d'Amazon.