Vue.js 2.0 : petit tutoriel (volume 2)

Nous poursuivons notre tutoriel Vue.js 2.0 avec ce second volet dans lequel vous apprendrez les différentes façons de modifier les données d’un composant et de quelle manière invoquer un service REST.

Si vous découvrez totalement Vue.js, je vous propose de débuter par le volume 1 toujours accessible ici. Le code source est quant à lui toujours disponible ici.

Modification des données d’un composant

Vue > Model

NB: cette partie décrit le composant se situant dans src/components/chap4.1

L’objectif ici est d’éditer une donnée d’un composant. Pour associer une zone de saisie du DOM à une donnée particulière d’un composant, un lien bi-directionnel (two-way binding) est établi entre les deux. L’établissement de ce lien passe par l’utilisation de la directive v-model permettant de spécifier à quelle donnée une zone éditable est reliée.

Si dans notre composant Hello.vue on souhaite pouvoir modifier la valeur du nom, du prénom et de la localisation :

Arrivé sur la page, les zones éditables sont automatiquement renseignées avec les valeurs par défaut des données du composant :

Si l’un des champs est modifié, la prise en compte est immédiate :

Ajoutons dans App.vue deux instances du même composant éditable :

Résultat :

Si on modifie l’état d’une instance d’un composant, en modifiant la valeur d’une de ses données par exemple, seule cette instance est impactée :

Model > Vue

NB: cette partie décrit le composant se situant dans src/components/chap4.2

Les données peuvent être modifiées à partir de la vue mais également à partir de fonctions javascript :

  • spécifiques à un composant donné, permettant de modifier son état à la demande (methods) ;
  • spécifiques à un composant donné, permettant de modifier son état automatiquement lorsque certaines données du composant sont mises à jour (computed) ;
  • portées par l’instance de Vue dans laquelle un composant est inclus, fonctions automatiquement invoquées durant différentes étapes du cycle de vie de cette instance.

Methods

Soit le composant Citizens.vue :

  • affichant un simple tableau listant les habitants d’une ville via une directive v-for permettant de parcourir la liste de citoyens contenue dans les données du composant ;
  • proposant un bouton permettant d’ajouter un habitant dans la liste.

/src/components/chap4.2/Citizens.vue

A chaque clic sur le bouton Add, la méthode addCitizen est invoquée pour ajouter un (même) habitant.

@click est un raccourci pour v-on:click. v-on est une directive permettant de détecter un événement survenant dans le DOM (ici un clic sur le bouton) et d’exécuter du code à son déclenchement (ici, un appel à la méthode addCitizen). VueJS permet d’agir sur de multiples événements :

  • @dblclick : lors d’un double-clic
  • @keyup.enter : au relâchement de la touche entrée
  • @keyup.esc : au relâchement de la touche esc

Dans cet exemple, la méthode addCitizen modifie l’état du composant (ses data) à chaque appel explicite (donc à chaque clic sur le bouton) :

Computed

Ajoutons à présent un compteur permettant d’afficher le nombre total d’habitants, compteur mis à jour automatiquement après avoir ajouté un habitant à la liste :

/src/components/chap4.2/Citizens.vue

{{counter}} permet d’indiquer à quel endroit afficher le résultat de la méthode counter qui se trouve dans la liste des fonctions computed : ces fonctions sont invoquées automatiquement mais ne sont exécutées que lorsque les données qu’elles manipulent sont modifiées. Ici, à chaque fois que la liste des habitants est modifiée, la fonction counter est exécutée sans qu’il y ait besoin d’y ajouter un appel explicite dans chacune des méthodes modifiant la liste (par exemple on ne l’appelle pas dans la méthode addCitizen). Si aucun habitant n’est ajouté, counter retournera automatiquement la précédente valeur calculée sans que son corps ne soit exécuté. On préférera donc ajouter une fonction dans computed plutôt que dans methods lorsque cette fonction doit réagir à la modification de l’état (d’une donnée) du composant afin que cette fonction ne soit pas réévaluée à chaque rendu.

Cycle de vie

Ajoutons des attributs à notre composant qui permettraient par exemple d’avoir une valeur par défaut dans notre liste d’habitants (on considère que la liste d’habitants est initialement vide dans le composant) :

/src/components/chap4.2/Citizens.vue

Ce composant doit être utilisé de la façon suivante dans App.vue :

/src/App.vue

Lors de l’accès initial à la page, la liste des citoyens est déjà renseignée avec un habitant :

Pour affecter la valeur des attributs du composant à ses données, on passe par l’utilisation des hooks, des fenêtres du cycle de vie d’une instance de Vue durant lesquelles des actions peuvent être déclenchées. Le cycle de vie d’une instance de Vue est le suivant (référence) :

vuejs2 component lifecycle

Dans notre exemple, pour modifier la valeur de data, on utilise la fonction mounted() qui se déclenche durant l’étape Mounted du cycle de vie. On a bien sûr la possibilité d’intervenir sur la vue à différents stades de son cycle de vie, certains d’entre eux n’étant pas accessibles lors d’un server side rendering (beforeMount, mounted, beforeUpdate, updated, beforeDestroy, destroyed).

Invoquer un service REST

NB: cette partie décrit le composant se situant dans src/components/chap5

Plutôt que d’initialiser la liste des habitants à travers la valeur des propriétés du composant, on va plutôt effectuer un appel à un service REST permettant de récupérer cette liste. Pour cela on va passer par le plugin vue-resource.

Installation

On va commencer par ajouter la dépendance qui va bien à notre projet. Dans le répertoire du projet, il suffit de lancer : npm i --save vue-resource
Automatiquement la dépendance sera ajoutée au fichier package.json et les modules nécessaires seront téléchargés dans le répertoire node_modules.

Bouchonnage

vue-resource ne dispose pas de fonctionnalité de bouchonnage, on va donc utiliser pour cela json-server.

Pour l’installer globalement, utilisez la commande : npm install -g json-server

Pour lancer le serveur, positionnez-vous à la racine du projet et exécutez : json-server --watch static\mocks\citizens.json

Si tout se déroule bien, le message suivant s’affiche :

Les urls disponibles :

Utilisation

Dans le composant Citizens.vue, on va importer le module vue-resource et indiquer qu’il doit être utilisé par Vue :

/src/components/chap5/Citizens.vue

L’utilisation de ce plugin donne accès aux services $http et $resource. Les deux permettent d’effectuer un appel http, le second est adapté à l’invocation de services REST (request path dynamique). Dans les deux cas de figure, l’invocation d’une opération retourne une promesse permettant de gérer les cas passants (dans notre exemple, si l’API est invoquée sans souci on affecte simplement le flux JSON reçu en réponse à la liste des citoyens) et les cas d’erreur.

Comme précédemment, on va utiliser l’étape mounted du cycle de vie pour initialiser notre composant, mais plutôt que de lui affecter des valeurs transmises par son composant parent, on va invoquer le bouchon du service web :

/src/components/chap5/Citizens.vue

ATTENTION : ne pas mettre de / à la fin de la racine de l’url ou au début de la ressource accédée.

Au moment d’accéder à la page, le service web est automatiquement invoqué et le flux JSON récupéré permet d’initialiser la liste :

vue-ressource faisait initialement partie intégrante du repo Vue.js et bien que tout à fait opérationnelle elle n’est plus aujourd’hui l’implémentation officielle de requêtage AJAX (référence). axios est une alternative intéressante puisqu’elle intègre par exemple un système de bouchonnage : nous vous donnerons quelques exemples plus tard.

That’s all folks !

Avec cette seconde partie vous avez les premiers éléments pour rendre vos applications dynamiques en mettant à jour l’état de vos composants et en affichant des données issues de vos services web.  J’espère que vous commencez à apprécier ce framework et sa simplicité ! On se retrouve bientôt pour le volume 3 avec la transmission d’informations d’un composant enfant vers un composant parent et la communication par événements.