Vue.js 2.0 : petit tutoriel (volume 3)

Et voici le troisième volet de notre tutoriel Vue.js 2.0 dans lequel nous abordons la transmission d’informations d’un composant enfant vers un composant parent et la communication par événements.

Les précédents volets sont toujours accessibles :

  • Volume 1 : pour créer un projet, créer un composant et transmettre des données d’un composant parent à un composant enfant ;
  • Volume 2 : pour apprendre à modifier les données d’un composant et de quelle façon invoquer un service REST.

Le code source est quant à lui toujours disponible ici. Bonne lecture !

Transmission d’une valeur d’un composant enfant à un composant parent

NB: cette partie décrit les composants se situant dans src/components/chap6 et dans src/pages/chap6

On a vu plus tôt la possibilité d’envoyer des valeurs d’un composant parent à un composant enfant par l’intermédiaire des propriétés d’un composant.

Dans le sens inverse, d’un composant enfant vers un composant parent, l’échange doit se faire par l’intermédiaire d’une transmission d’événements.

Considérons un composant CitizenPage.vue importé dans App.vue et incluant deux autres composants, Citizens.vue développé précédemment et listant l’ensemble des citoyens de la ville, et Citizen.vue permettant d’afficher le détail d’un citoyen :


/src/pages/Chap6/CitizenPage.vue

…pour obtenir :

L’idée est de donner la possibilité de cliquer sur un citoyen de la liste (à gauche, le composant Citizens.vue) et qu’automatiquement les informations détaillées du citoyen sélectionné soient affichées dans le composant Citizen.vue (à droite). Pour cela, il faut qu’en cliquant sur une ligne de la liste un événement soit émis par le composant Citizens.vue puis capté par Citizen.vue.

Emission d’un événement par un composant enfant

L’objectif ici est de détecter puis d’émettre le citoyen sélectionné.

Dans Citizens.vue on détecte l’événement “clic de souris sur un item de la liste” avec la directive v-on:click (raccourci @click) et on y associe l’exécution d’une méthode diffusant l’identifiant du citoyen sélectionné dans la liste :


/src/components/chap6/Citizens.vue

A travers le service $emit, un événement ‘selected’ est déclenché et le message associé à cet événement correspond à l’objet citoyen de la ligne sélectionnée.

Réception d’un événement par le composant parent et diffusion à un autre composant enfant

L’objectif à présent est de faire en sorte que le composant parent puisse réceptionner l’événement émis pour ensuite le transmettre à un autre composant enfant.

Dans le composant CitizenPage.vue on modifie les éléments et de la façon suivante :


/src/pages/chap6/CitizenPage.vue

Quelques explications :

  1. Dans le composant parent CitizenPage.vue l’événement ‘selected’ émis par le composant Citizens.vue est capté au niveau de l’élément HTML auquel il est rattaché dans le template () via la directive v-on:<EVENT_NAME> avec ici <EVENT_NAME>=selected.
  2. Le déclenchement de la méthode setSelected, permettant de valoriser un attribut selectedCitizen du composant parent, survient à réception d’un événement ‘selected’ émis par le composant enfant. Le contenu de l’événement est transmis à la méthode via $event.
  3. Pour transmettre la valeur sélectionnée au composant Citizen.vue, il suffit de passer par un attribut dynamique “bindé” sur la donnée selectedCitizen du composant.

Dans Citizen.vue, on a une simple propriété citizen :


/src/components/chap6/Citizen.vue

Finalement, on obtient :

Communication directe entre composants

NB: cette partie décrit les composants se situant dans src/components/chap7 et dans src/pages/chap7

On peut faire beaucoup plus simple que l’exemple proposé ci-dessus en transmettant directement l’événement ‘citoyen sélectionné’ émis par le composant Citizens.vue au composant Citizen.vue, sans passer par le composant parent CitizenPage.vue.

De plus, on va éviter de faire transiter l’intégralité de l’objet : on va se contenter de faire circuler l’identifiant du citoyen sélectionné et le composant Citizen.vue effectuera un appel à un autre service bouchon (voir le Volume 2) chargé de récupérer les informations détaillées d’un citoyen donné.

Emission d’un événement

L’objectif ici est d’émettre l’identifiant du citoyen sélectionné.

La communication directe entre composants se base sur la notion d’événements et de listener. L’idée est qu’un composant A émet un événement sur un “bus d’événements” partagé entre tous les composants et que les autres composants intéressés s’abonnent à cet événement pour le capter et effectuer un traitement particulier.

On déclare ce “bus” global, une instance de Vue dédiée, dans main.js :


/src/main.js

Si on reprend le composant Citizens.vue, dans la méthode déclenchée par le clic on émet cette fois-ci non plus l’événement via this.$emit mais via bus.$emit (et on transmet uniquement l’identifiant du citoyen sélectionné) :


/src/components/chap7/Citizens.vue

Réception d’un événement

L’objectif à présent est de réceptionner l’identifiant du citoyen sélectionné.

Pour que le composant Citizen.vue récupère l’identifiant du citoyen sélectionné, il suffit au moment de sa création (donc dans son hook created()) de l’”abonner” à l’événement ‘selectedCitizen’ via le service $on prenant simplement en arguments le nom de l’événement et une fonction permettant d’effectuer un traitement à réception d’un événement portant ce nom.

Dans notre exemple, on va faire un appel au bouchon http://localhost:3000/citizens/{id} pour récupérer les informations détaillées de l’utilisateur qui nous intéresse :


/src/components/chap7/Citizen.vue

Ce qui nous donne :

Hasta la vista, baby !

Clap de fin pour ce troisième volet du tutoriel dédié à la découverte de Vue.js 2.0. La communication événementielle est une arme puissante, qui vous permettra d’embarquer des composants réactifs dans vos applications. Mais il faut l’utiliser avec parcimonie et discernement. Dans l’épisode 4, je vous sensibiliserai aux problématiques liées à l’excès de communication par événements et vous proposerai d’étudier de près le pattern Gestionnaire d’état et son implémentation Vue.js officielle : vuex.