Ractive.js - Applications Web simplifiées

Publié: 2022-03-11

Dans le paysage actuel de prolifération rapide des frameworks et bibliothèques JavaScript, sélectionner celui sur lequel vous souhaitez baser votre développement peut être un véritable défi. Après tout, une fois que vous avez choisi d'utiliser un framework particulier, la migration de votre code vers un autre est une tâche non triviale que vous n'aurez peut-être jamais le temps ou le budget pour effectuer.

Alors, pourquoi Ractive.js ?

Contrairement à d'autres outils qui génèrent du HTML inerte, Ractive transforme les modèles en plans pour les applications qui sont interactives par défaut. Et bien que l'on puisse certainement affirmer que la contribution de Ractive est plus évolutive que révolutionnaire, sa valeur est néanmoins significative.

Ce qui rend Ractive si utile, c'est qu'il offre des fonctionnalités puissantes, mais le fait d'une manière rafraîchissante et simple à utiliser pour le développeur. De plus, il est assez élégant, rapide, discret et petit.

Dans cet article, nous allons parcourir le processus de création d'une application de recherche Ractive simple, en démontrant certaines des fonctionnalités clés de Ractive et la manière dont elle contribue à simplifier les applications Web et le développement.

Ractive.js et applications Web

Qu'est-ce que Ractive.js ?

Ractive a été créé à l'origine pour résoudre le problème de liaison de données d'une manière plus élégante. À cette fin, il prend des modèles et les transforme en une représentation virtuelle légère du DOM afin que, lorsque les données changent, le vrai DOM est mis à jour de manière intelligente et efficace.

Mais il est vite devenu évident que l'approche et l'infrastructure employées par Ractive pouvaient également être utilisées pour faire d'autres choses plus efficacement. Il peut, par exemple, s'occuper automatiquement de choses telles que la réutilisation des gestionnaires d'événements et leur suppression automatique lorsqu'ils ne sont plus nécessaires. La délégation d'événement devient inutile. Comme pour la liaison de données, cette approche empêche le code de devenir lourd à mesure qu'une application se développe.

Des fonctionnalités clés telles que la liaison bidirectionnelle, les animations et la prise en charge de SVG sont fournies prêtes à l'emploi, et des fonctionnalités personnalisées peuvent être facilement ajoutées via des plugins.

Alors que certains outils et frameworks vous obligent à apprendre un nouveau vocabulaire et à structurer votre application d'une manière particulière, Ractive travaille pour vous, et non l'inverse. Il s'intègre également bien avec d'autres bibliothèques.

Notre exemple d'application

Notre exemple d'application sera utilisé pour rechercher la base de données Toptal des développeurs en fonction des compétences. Notre application aura deux vues :

  • Recherche : liste de compétences avec champ de recherche en ligne
  • Résultats : vue des compétences incluant la liste des développeurs

Pour chaque développeur, nous afficherons son nom, sa photo, une courte description et une liste de compétences (chaque compétence sera liée à la vue de compétence correspondante).

(Remarque : des liens vers une instance de travail en ligne de l'application et le référentiel de code source sont tous deux fournis à la fin de cet article.)

Afin de maintenir notre objectif principal sur le framework Ractive, nous utiliserons un certain nombre de simplifications qui ne devraient normalement pas être effectuées en production :

  • Thème par défaut. Nous utiliserons Bootstrap avec le thème par défaut pour le style, plutôt que de personnaliser le thème pour l'adapter au style de votre application.
  • Dépendances. Nous ajouterons nos dépendances en tant que scripts séparés qui définissent des variables globales (plutôt que d'utiliser des modules ES6, ou CommonJS, ou AMD avec un chargeur approprié pour le développement et l'étape de construction pour la production).
  • Données statiques. Nous utiliserons des données statiques que j'ai préparées en grattant les pages publiques du site Toptal.
  • Pas de routage côté client. Cela signifie que l'URL restera la même lorsque nous basculerons entre les vues. Vous ne devriez certainement pas faire cela pour les SPA, bien que cela puisse convenir pour certains petits composants interactifs. Ractive n'a pas d'implémentation de routeur intégrée, mais il peut être utilisé avec des routeurs tiers, comme illustré dans cet exemple.
  • Modèles définis à l'intérieur des balises de script en HTML. Ce n'est pas forcément une mauvaise idée, surtout pour les petites applications, et cela présente certains avantages (c'est simple, et vous pouvez traiter ces modèles côté client avec vos modèles côté serveur, par exemple pour l'internationalisation). Mais pour les applications plus volumineuses, vous pouvez bénéficier de la pré-compilation (c'est-à-dire de la pré-analyse des modèles vers la représentation JS interne.

Commençons avec les applications Web

OK, cela dit, commençons à créer l'application. Nous allons le faire de manière itérative, en ajoutant des fonctionnalités plus petites une par une et en explorant les concepts au fur et à mesure que nous les rencontrons.

Commençons par créer un dossier avec deux fichiers à l'intérieur : index.html et script.js . Notre application sera extrêmement simple et fonctionnera à partir du protocole file:// afin d'éviter d'avoir à démarrer le serveur de développement (bien que vous puissiez le faire si vous le souhaitez).

La page de recherche

Nous commencerons par implémenter la page de recherche où l'utilisateur peut sélectionner une compétence pour laquelle trouver des développeurs correspondants dans la base de données Toptal.

Squelette HTML

Commençons par cette page HTML triviale :

 <html> <head> <title>Toptal Search</title> <!-- LOAD BOOTSTRAP FROM THE CDN --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"> </head> <body> <!-- SOME BASIC STATIC CONTENT --> <div class="container"> <h1>Toptal Search</h1> </div> <!-- LOAD THE JAVASCRIPT LIBRARIES WE NEED --> <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.9.3/lodash.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/ractive/0.7.3/ractive.min.js"></script> <!-- LOAD THE DATA --> <script src="https://rawgit.com/emirotin/toptal-blog-ractive/master/data.js"></script> <!-- LOAD OUR SCRIPT --> <script src="script.js"></script> </body> </html>

Comme vous pouvez le constater, il s'agit d'un document HTML5 trivial. Il charge Bootstrap à partir du CDN, Lodash (une impressionnante bibliothèque de manipulation de données) et Ractive.js.

Ractive ne nécessite pas de consacrer toute la page à SPA, nous pouvons donc avoir du contenu statique. Dans notre cas, il s'agit d'un élément conteneur et du titre de la page.

Enfin, nous chargeons les données que j'ai préparées pour la démo et le script qui contiendra notre programme.

OK, maintenant que notre squelette HTML est en place, commençons à ajouter de vraies fonctionnalités.

Liste des compétences

L'une des choses que j'aime particulièrement à propos de Ractive est la façon dont il vous apprend à réfléchir à la représentation finale (HTML) que vous souhaitez obtenir, puis vous permet de vous concentrer sur l'écriture des morceaux de code nécessaires pour y parvenir.

Alors d'abord, construisons une liste de compétences comme point de vue initial. Faire cela implique simplement:

  • Ajout d'un élément HTML dans lequel la liste des compétences sera affichée.
  • Ajout d'un petit extrait de code de modèle à notre code HTML.
  • Écrire du JavaScript bref et simple qui fournit les données au modèle, pour le rendre dans l'élément HTML que nous avons ajouté.

Les mods du HTML sont les suivants :

 <div class="container"> <h1>Toptal Search</h1> <div></div> <!-- THIS IS THE NEW HTML ELEMENT --> </div> <!-- THIS IS THE SMALL SNIPPET OF TEMPLATE CODE --> <script type="text/html"> <div class="row"> {{#each skills}} <span class="col-xs-3"> <a href="#" class="label label-primary">{{this}}</a> </span> {{/each}} </div> </script>

Il n'y a pas de convention spéciale avec Ractive pour spécifier l'élément HTML devant recevoir les données à afficher, mais la façon la plus simple de le faire est d'ajouter un ID à l'élément. J'utilise généralement l'identifiant "root" à cette fin. Nous verrons bientôt comment il est utilisé lorsque Ractive est initialisé. Pour les curieux, il existe d'autres façons de spécifier l'élément racine.

L'élément de script légèrement maladroit avec type="text/html" est une astuce astucieuse pour obtenir un morceau de HTML chargé par le navigateur sans qu'il soit analysé ou rendu, car les navigateurs ignorent les scripts de type inconnu. Le contenu du script est un modèle de type Moustache/Handlebars (bien que Ractive ait quelques extensions).

Nous écrivons d'abord le code du modèle en supposant que nous avons accès au tableau des compétences. Nous utilisons la directive moustache {{#each}} pour définir l'itération. À l'intérieur de la directive, l'élément actuel est accessible en tant que this . Encore une fois, nous supposons que la variable skills contient un tableau de chaînes, nous la rendons donc simplement avec une moustache d'interpolation {{this}} .

OK, c'est le HTML. Mais qu'en est-il du JavaScript ? C'est là que se produit la "magie" qui fournit les données au modèle ::

 (function () { var skills = DB.skills, developers = DB.developers; var app = new Ractive({ el: '#root', template: '#tpl-app', data: { skills: _.keys(DB.skills) } }); }());

Impressionnant, non ? En seulement 10 lignes de code, nous pouvons :

  1. "Récupérer" les données de la "DB".
  2. Instanciez une nouvelle application Ractive.
  3. Dites-lui de rendre à l'intérieur de l'élément avec .
  4. Dites-lui d'utiliser un élément de script avec pour obtenir le modèle (il existe également d'autres façons de le faire).
  5. Passez les données initiales (nous verrons comment les modifier au moment de l'exécution), ou "portée" si vous êtes habitué à la terminologie angulaire.
  6. Utilisez la méthode des keys lodash pour obtenir les noms des compétences que nous utilisons comme clés d'objet dans la "DB".

Donc, fondamentalement, avec ce script, nous indiquons au framework quoi faire, mais pas comment le faire. Le modèle déclare comment, ce que je trouve personnellement assez étonnant et naturel.

J'espère que vous commencez à avoir l'idée, alors maintenant implémentons quelque chose de plus utile en plus de ce que nous avons.

Recherche de compétences

La page de recherche, bien sûr, a besoin d'un champ de recherche. Et nous aimerions qu'il fournisse une capacité interactive par laquelle lorsque l'utilisateur tape dans la zone de recherche, la liste des compétences est filtrée uniquement celles qui contiennent la sous-chaîne saisie (le filtrage étant insensible à la casse).

Comme d'habitude avec Ractive, on commence par définir le template (en pensant quelles nouvelles variables de contexte seront nécessaires, et ce qui changerait par rapport à la gestion des données) :

 <div class="container"> <h1>Toptal Search</h1> <div></div> </div> <!-- THIS IS THE SMALL SNIPPET OF TEMPLATE CODE --> <script type="text/html"> <!-- HERE'S OUR SEARCH BOX --> <div class="row"> <form class="form-horizontal col-xs-6 col-xs-offset-6"> <input type="search" class="form-control" value="{{ skillFilter }}" placeholder="Type part of the skill name here"> </form> </div> <hr> <!-- NOW INSTEAD OF DISPLAYING ALL SKILLS, WE INVOKE A TO-BE-CREATED JAVASCRIPT skills() FUNCTION THAT WILL FILTER THE SKILL LIST DOWN TO THOSE THAT MATCH THE TEXT ENTERED BY THE USER --> <div class="row"> {{#each skills()}} <span class="col-xs-3"> <a href="#" class="label label-primary">{{this}}</a> </span> {{/each}} </div> </script>

Pas tant de changements, mais encore une bonne quantité à apprendre.

Tout d'abord, nous avons ajouté un nouveau <div> contenant notre champ de recherche. Il est assez évident que nous voulons connecter cette entrée à une variable (à moins que vous ne soyez nostalgique des bons vieux jours de soupe jQuery). Ractive prend en charge ce que l'on appelle la liaison bidirectionnelle, ce qui signifie que votre code JS peut récupérer une valeur sans avoir à la lire manuellement à partir du DOM. Dans notre cas, cela est accompli en utilisant la moustache d'interpolation value="{{ skillFilter }}" . Ractive comprend que nous voulons lier cette variable à l'attribut value de l'entrée. Il surveille donc l'entrée pour nous et met automatiquement à jour la variable. Assez soigné avec seulement 1 ligne de HTML.

Deuxièmement, comme expliqué dans le commentaire de l'extrait de code ci-dessus, au lieu d'afficher toutes les compétences, nous allons créer une fonction skills() JS qui filtrera la liste des compétences et ne renverra que celles qui correspondent au texte saisi par l'utilisateur :

 // store skill list in a variable outside of Ractive scope var skillNames = _.keys(DB.skills); var app = new Ractive({ el: '#root', template: '#tpl-app', data: { // initializing the context variable is not strictly // required, but it is generally considered good practice skillFilter: null, // Define the skills() function right in our data object. // Function is available to our template where we call it. skills: function() { // Get the skillFilter variable from the Ractive instance // (available as 'this'). // NOTE WELL: Our use of a getter here tells Ractive that // our function has a *dependency* on the skillFilter // value, so this is significant. var skillFilter = this.get('skillFilter'); if (!skillFilter) { return skillNames; } skillFilter = new RegExp(_.escapeRegExp(skillFilter), 'i') return _.filter(skillNames, function(skill) { return skill.match(skillFilter); }); } } });

Bien que cela soit propre et simple à mettre en œuvre, vous vous demandez peut-être quel est son impact sur les performances. Je veux dire, on va appeler une fonction à chaque fois ? Eh bien, à chaque fois quoi ? Ractive est assez intelligent pour restituer uniquement des parties du modèle (et appeler toutes les fonctions à partir de celles-ci) lorsque leurs dépendances (variables) changent (Ractive sait quand cela se produit grâce à l'utilisation de setters).

Incidemment, pour ceux qui souhaitent aller plus loin, il existe également une manière plus élégante de le faire en utilisant une propriété calculée, mais je vous laisse jouer avec vous-même si vous le souhaitez.

La page des résultats

Maintenant que nous avons une liste de compétences interrogeable assez utilisable, passons à la vue des résultats où la liste correspondante des développeurs sera affichée.

Basculer vers et depuis la vue des compétences

Il existe évidemment plusieurs façons de mettre cela en œuvre. J'ai choisi l'approche selon laquelle il y a deux points de vue différents selon qu'une compétence a été sélectionnée ou non. Si tel est le cas, nous affichons la liste des développeurs correspondants ; sinon, nous affichons la liste des compétences et le champ de recherche.

Ainsi, pour commencer, lorsque l'utilisateur sélectionne (c'est-à-dire clique sur) un nom de compétence, la liste des compétences doit être masquée et le nom de la compétence doit être affiché à la place comme en-tête de page. Inversement, sur la vue des compétences sélectionnées, il doit y avoir un moyen de fermer cette vue et de revenir à la liste des compétences.

Voici notre premier pas dans cette voie :

 <script type="text/html"> <!-- PARTIAL IS A NEW CONCEPT HERE --> {{#partial skillsList}} <div class="row"> <form class="form-horizontal col-xs-6 col-xs-offset-6"> <input type="search" class="form-control" value="{{ skillFilter }}" placeholder="Type part of the skill name here"> </form> </div> <hr> <div class="row"> {{#each skills()}} <span class="col-xs-3"> <!-- MAKE OUR SKILLS CLICKABLE, USING PROXY EVENTS --> <a href="#" class="label label-primary" on-click="select-skill:{{this}}">{{this}}</a> </span> {{/each}} </div> {{/partial}} {{#partial skillView}} <h2> <!-- DISPLAY SELECTED SKILL AS HEADING ON THE PAGE --> {{ currentSkill }} <!-- CLOSE BUTTON TAKES USER BACK TO SKILLS LIST --> <button type="button" class="close pull-right" on-click="deselect-skill">&times; CLOSE</button> </h2> {{/partial}} <!-- PARTIALS ARE NOT IN THE VIEW UNTIL WE EXPLICITLY INCLUDE THEM, SO INCLUDE THE PARTIAL RELEVANT TO THE CURRENT VIEW. --> {{#if currentSkill}} {{> skillView}} {{else}} {{> skillsList}} {{/if}} </script>

OK, il se passe BEAUCOUP de choses ici.

Tout d'abord, pour permettre l'implémentation de cela en deux vues différentes, j'ai déplacé tout ce que nous avions jusqu'à présent (c'est-à-dire la vue de liste) vers quelque chose appelé un partiel. Un partiel est essentiellement un morceau de code de modèle que nous allons inclure dans un endroit différent (bientôt).

Ensuite, nous voulons rendre nos compétences cliquables, et quand on clique dessus, nous voulons naviguer vers la vue de compétence correspondante. Pour cela, nous utilisons quelque chose appelé événements proxy, par lequel nous réagissons à un événement physique (au clic, le nom est celui compréhensible par Ractive) et le proxy à l'événement logique (select-skill, le nom est ce que nous l'appelons ) en passant l'argument (comme vous vous en souvenez probablement, cela représente le nom de la compétence ici).

(Pour votre information, une autre syntaxe d'appels de méthode existe pour accomplir la même chose.)

Ensuite, nous supposons (à nouveau) que nous aurons une variable appelée currentSkill qui portera le nom de la compétence sélectionnée (le cas échéant), ou sera vide si aucune compétence n'est sélectionnée. Nous définissons donc un autre partiel qui affiche le nom de la compétence actuelle, et a également un lien "FERMER" qui devrait désélectionner la compétence.

Pour le JavaScript, le principal ajout est le code permettant de s'abonner aux événements select-skill et deselect-skill, en mettant à jour currentSkill (et skillFilter ) en conséquence :

 var app = new Ractive({ el: '#root', template: '#tpl-app', data: { skillFilter: null, currentSkill: null, // INITIALIZE currentSkill TO null // skills function remains unchanged skills: function() { var skillFilter = this.get('skillFilter'); if (!skillFilter) { return skillNames; } skillFilter = new RegExp(_.escapeRegExp(skillFilter), 'i') return _.filter(skillNames, function(skill) { return skill.match(skillFilter); }); } } }); // SUBSCRIBE TO LOGICAL EVENT select-skill app.on('select-skill', function(event, skill) { this.set({ // SET currentSkill TO THE SKILL SELECTED BY THE USER currentSkill: skill, // RESET THE SEARCH FILTER skillFilter: null }); }); // SUBSCRIBE TO LOGICAL EVENT deselect-skill app.on('deselect-skill', function(event) { this.set('currentSkill', null); // CLEAR currentSkill });

Répertorier les développeurs pour chaque compétence

Après avoir préparé la nouvelle vue pour la compétence, nous pouvons maintenant ajouter de la viande - la liste réelle des développeurs que nous avons pour cette liste. Pour cela, nous développons le partiel pour cette vue comme suit :

 {{#partial skillView}} <h2> {{ currentSkill }} <button type="button" class="close pull-right" on-click="deselect-skill">&times; CLOSE</button> </h2> {{#each skillDevelopers(currentSkill)}} <div class="panel panel-default"> <div class="panel-body"> {{ this.name }} </div> </div> {{/each}} {{/partial}}

J'espère qu'à ce stade, vous avez une idée de ce qui se passe ici : nous avons ajouté une nouvelle section d'itération à notre partiel skillView qui itère sur le résultat d'une nouvelle fonction skillDevelopers que nous allons écrire juste après. Pour chaque développeur du tableau (renvoyé par cette fonction skillDevelopers ), nous rendons un panneau et affichons le nom du développeur. Notez que je pourrais utiliser la forme implicite {{name}} ici et Ractive trouverait l'attribut approprié en recherchant la chaîne de contexte à partir du contexte actuel (qui dans notre cas est l'objet développeur lié par {{#each}} ), mais Je préfère être explicite. Plus d'informations sur les contextes et les références sont disponibles dans la documentation de Ractive.

Et voici l'implémentation de la fonction skillDevelopers() :

 skillDevelopers: function(skill) { // GET THE SKILL OBJECT FROM THE “DB” skill = skills[skill]; // SAFETY CHECK, RETURN EARLY IN CASE OF UNKNOWN SKILL NAME if (!skill) { return; } // MAP THE DEVELOPER'S IDs (SLUGS) TO THE // ACTUAL DEVELOPER DETAIL OBJECTS return _.map(skill.developers, function(slug) { return developers[slug]; }); }

Élargir l'entrée pour chaque développeur

Maintenant que nous avons une liste de travail des développeurs, il est temps d'ajouter plus de détails, et une jolie photo bien sûr :

 {{#partial skillView}} <h2> {{ currentSkill }} <button type="button" class="close pull-right" on-click="deselect-skill">&times; CLOSE</button> </h2> {{#each skillDevelopers(currentSkill)}} <div class="panel panel-default"> <div class="panel-body media"> <div class="media-left"> <!-- ADD THE PHOTO --> <img class="media-object img-circle" width="64" height="64" src="{{ this.photo }}" alt="{{ this.name }}"> </div> <div class="media-body"> <!-- MAKE THE DEVELOPER'S NAME A HYPERLINK TO THEIR PROFILE --> <a class="h4 media-heading" href="{{ this.url }}" target="_blank"> {{ this.name }}</a> <!-- ADD MORE DETAILS (FROM THEIR PROFILE) --> <p>{{ this.desc }}</p> </div> </div> </div> {{/each}} {{/partial}}

Rien de nouveau ici du côté Ractive, mais une utilisation un peu plus intensive des fonctionnalités de Bootstrap.

Affichage d'une liste cliquable des compétences de développeur

Nous avons fait de bons progrès jusqu'à présent, mais une caractéristique qui manque encore est l'autre côté de la relation entre les compétences et les développeurs ; à savoir, nous voulons afficher les compétences de chaque développeur et nous voulons que chacune de ces compétences soit un lien cliquable qui nous amène à la vue des résultats pour cette compétence.

Mais attendez… Je suis sûr que nous avons déjà exactement la même chose dans la liste des compétences. Oui, en fait, nous le faisons. C'est dans la liste cliquable des compétences, mais cela vient d'un éventail différent de l'ensemble de compétences de chaque développeur. Pourtant, ceux-ci sont suffisamment similaires pour que ce soit un signe clair pour moi que nous devrions réutiliser ce morceau de HTML. Et à cette fin, les partiels sont nos amis.

(Remarque : Ractive a également une approche plus avancée pour les morceaux réutilisables d'une vue, appelés composants. Ils sont vraiment très utiles, mais par souci de simplicité, nous n'en discuterons pas maintenant.)

Voici donc comment nous y parvenons en utilisant des partiels (et notez, incidemment, que nous sommes en mesure d'ajouter cette fonctionnalité sans ajouter une seule ligne de code JavaScript !) :

 <!-- MAKE THE CLICKABLE SKILL LINK INTO ITS OWN “skill” PARTIAL --> {{#partial skill}} <a href="#" class="label label-primary" on-click="select-skill:{{this}}">{{this}}</a> {{/partial}} {{#partial skillsList}} <div class="row"> <form class="form-horizontal col-xs-6 col-xs-offset-6"> <input type="search" class="form-control" value="{{ skillFilter }}" placeholder="Type part of the skill name here"> </form> </div> <hr> <div class="row"> {{#each skills()}} <!-- USE THE NEW “skill” PARTIAL --> <span class="col-xs-3">{{> skill}}</span> {{/each}} </div> {{/partial}} {{#partial skillView}} <h2> {{ currentSkill }} <button type="button" class="close pull-right" on-click="deselect-skill">&times; CLOSE</button> </h2> {{#each skillDevelopers(currentSkill)}} <div class="panel panel-default"> <div class="panel-body media"> <div class="media-left"> <img class="media-object img-circle" width="64" height="64" src="{{ this.photo }}" alt="{{ this.name }}"> </div> <div class="media-body"> <a class="h4 media-heading" href="{{ this.url }}" target="_blank">{{ this.name }}</a> <p>{{ this.desc }}</p> <p> <!-- ITERATE OVER THE DEVELOPER'S SKILLS --> {{#each this.skills}} <!-- REUSE THE NEW “skill” PARTIAL TO DISPLAY EACH DEVELOPER SKILL AS A CLICKABLE LINK --> {{> skill}}&nbsp; {{/each}} </p> </div> </div> </div> {{/each}} {{/partial}}

J'ai déjà la liste des compétences attachée à l'objet du développeur que nous avons récupéré de la "DB", donc j'ai juste un peu changé le modèle : j'ai déplacé la ligne qui rend l'étiquette de compétence vers un partiel et j'ai utilisé ce partiel là où cette ligne était à l'origine.

Ensuite, lorsque j'itère sur les compétences du développeur, je peux réutiliser ce même nouveau partiel pour afficher également chacune de ces compétences sous forme de lien cliquable. De plus, cela remplace également l'événement select-skill si vous vous en souvenez, en passant le même nom de compétence. Cela signifie que nous pouvons l'inclure n'importe où (avec le contexte approprié) et nous obtiendrons une étiquette cliquable qui mène à la vue des compétences !

Touche finale — Préchargeur

OK, nous avons maintenant une application fonctionnelle de base. Il est propre et fonctionne rapidement, mais il faut encore un certain temps pour le charger. (Dans notre cas, cela est en partie dû au fait que nous utilisons des sources non concaténées et non minifiées, mais dans une application du monde réel, il peut y avoir d'autres raisons importantes, telles que le chargement des données initiales).

Donc, comme dernière étape, je vais vous montrer une astuce pour ajouter une animation de préchargement qui sera supprimée dès que Ractive rendra notre application :

 <div class="container"> <h1>Toptal Search</h1> <div> <div class="progress"> <div class="progress-bar progress-bar-striped active"> Loading... </div> </div> </div> </div>

Alors, quelle est la magie ici? C'est en fait assez simple. J'ai ajouté du contenu (c'est une barre de progression animée Bootstrap, mais cela pourrait être un GIF animé, ou autre) directement à notre élément racine. Je pense que c'est assez intelligent - pendant que nos scripts se chargent, l'utilisateur voit l'indicateur de chargement (puisqu'il ne dépend pas du JavaScript, il peut être affiché immédiatement). Cependant, dès que l'application Ractive est initialisée, Ractive écrasera le contenu de l'élément racine (et effacera ainsi l'animation de préchargement) avec le modèle rendu. De cette façon, nous sommes en mesure d'obtenir cet effet juste un morceau de HTML statique et 0 lignes de logique. Je pense que c'est plutôt cool.

Conclusion

Pensez à ce que nous avons accompli ici et à la facilité avec laquelle nous l'avons accompli. Nous avons une application assez complète : elle affiche une liste de compétences, permet de les parcourir rapidement (et prend même en charge la mise à jour interactive de la liste des compétences au fur et à mesure que l'utilisateur tape dans le champ de recherche), permet de naviguer vers une compétence particulière et de revenir en arrière, et répertorie les développeurs pour chaque compétence sélectionnée. De plus, nous pouvons cliquer sur n'importe quelle compétence répertoriée par n'importe quel développeur pour accéder à la liste des développeurs possédant cette compétence. Et tout cela avec moins de 80 lignes de HTML et moins de 40 lignes de JavaScript. À mon avis, c'est assez impressionnant et en dit long sur la puissance, l'élégance et la simplicité de Ractive.

Une version de travail de l'application est disponible en ligne ici et le code source complet est public et disponible ici.

Bien sûr, nous avons à peine effleuré la surface dans cet article de ce qui est possible avec le framework Ractive. Si vous aimez ce que vous avez vu jusqu'à présent, je vous encourage fortement à démarrer avec la configuration de 60 secondes de Ractive et à commencer à explorer par vous-même tout ce que Ractive a à offrir.