Vue.js - Listes et composants

Listes

Comme dans beaucoup d'application, nous aurons besoin d'afficher des listes de données.

Associer un tableau à des éléments avec v-for

Nous pouvons utiliser la directive v-for pour faire le rendu d’une liste d’éléments en nous basant sur un tableau.

La directive v-for utilise une syntaxe spécifique de la forme item in items, où items représente le tableau source des données et où item est un alias représentant l’élément du tableau en cours d’itération, l'élément actuellement parcourus.

<ul>
  <li v-for="item in items">
    {{ item.message }}
  </li>
</ul>
const items = ref([
    { message: 'Foo' },
    { message: 'Bar' }
])

Résultat :

  • Foo

  • Bar

Exemple avec un tableau simple

  • 5 : <li> contant une boucle v-for qui va se répéter pour chaque éléments du tableau listeDeCourses.

    • Chaque élément du tableau listeDeCourses sera, à sont tour, injecté dans l'alias article puis affiché comme contenu du <li> : {{ article }}

  • 13 : Déclaration du tableau listeDeCourses

Exemple avec un tableau d'objets

  • 5 - 8 : <li> contant une boucle v-for qui va se répéter pour chaque éléments du tableau tasks et affichage des différentes propriétés de l'objet retourné : {{ task.name }}

  • 16 - 32 : Déclaration du tableau des tâches tasks

    • Chaque tâche est un objet avec un nom name, une date dueDate et un heure dueTime de fin.

Attribut unique :key

Afin d'identifier un élément d'une liste dans le but de le manipuler (supprimer, modifier, ... ), on utilise l’attribut :key dont la valeur doit être unique dans une même liste.

circle-info

Il est conseillé de toujours préciser:key avec v-for.

Ceci est utile autant pour l'optimisation que pour les transition avec le composant <Transition /> de Vue.js

Si les éléments de la liste ne possèdent pas d'identifiant, il suffit d'utiliser leur index, leur position dans le tableau, comme présenté ci-après.

Exemple de liste avec bouton de suppression d'un élément

  • 5 : Récupération de l'index dans v-for et création d'un attribut :key avec index comme valeur.

  • 8 : Création d'un <button> qui au click appelle la méthode deleteTask en lui passant l'index en paramètre.

  • 35 - 38 : Création de la méthode deleteTask

Composants

Une page se compose souvent de plusieurs parties: menu, entête, boutons, ... . Afin de faciliter la maintenance et la réutilisation de ces différents éléments, ils seront séparés dans plusieurs fichiers. Ce sont ses éléments que nous appelons des composants.

Les composants se trouvent dans le dossier src/components des projets Quasar.

Créer un composant

Pour créer un composant, il suffit de créer un nouveau fichier .vue dans le dossier src/components/.

Si vous souhaitez savoir comment déclarer un composant un Vue.js de manière classique, voir la documentations officielle : https://fr.vuejs.org/v2/guide/components-registration.htmlarrow-up-right.

Exemple création d'un composant Task.vue

Ce composant contient toutes les informations d'une tâche.

Créer un fichier Task.vue dans le dossier src/components/ de votre projet Qasar.

Et voilà ! Vous venez de créer votre 1er composant 🎉

Utiliser un composant dans un autre composant, dans une page

En réalité, nos page sont également des composants Vue, vous aviez donc déjà travaillé avec des composants.

Pour pouvoir utiliser un composant dans un autre composant, il faut l'importer. Voici un exemple d'importation du composant Task dans un autre composant Vue.

Exemple importation du composant Task.vue

Remplacez le code de votre fichier pages/Index.vue avec le code de l’exemple ci-apès.

  • 4 : Utilisation du composant Task dans le template <task></task>

    • Les balises <task></task> seront remplacée par le contenu du <template> du composant Task soit : <div>Je suis une tâche</div>

  • 11 - 13 : Importation du composant Task dans notre page Index.vue

    • Sans cette importation, impossible d'utiliser le composant Task dans la page

Passer des données à un composant via des propriétés

Pour l'instant notre composant Task est statique et afficher toujours la même chose. Nous allons maintenant y passer des données a afficher.

Pour que deux composants échanges des données, il doivent avoir une relation directe de type parent - enfant.

  • composant parent : Le composant qui importe un autre composant

  • composant enfant : le composant importé.

Pour passer des données à un composant, il faut que le composant enfant possède des propriétés.

Nous allons donc déclarer une propriété task et une propriété index à notre composant Task.vue.

  • task : Cette propriété permettra de transmettre un objet contenant toutes les informations d'une tâche (nom, date et heure).

  • index : la position de la tâche dans le tableau tasks

Exemple création des propriétés task et index

Dans le composant Task.vue :

  • 2 - 6 : Création du template avec les infos de la tâche et son index

    • Le template retourne un élément de liste <li> contant toutes les infos de la tâche.

    • {{ task }} permet d'accéder à une propriété d'un composant comme pour ses données et propriétés composées.

  • 12 - 15 : Déclaration des propriétés du composant Task.vue

    • task : doit être de type Object et est obligatoire

    • index : doit être de type Number et est obligatoire

Dans la page Index.vue :

  • 5 - 9 : Création d'une boucle v-for sur le composant <task> qui parcours le tableau tasks et injecte au composant la tâche et l'index en cours via les propriétés :task et :index.

    • Pour passer une donnée à une propriété d'un composant, on écrit le nom de la propriété précédé de :.

  • 20 - 40 : Déclaration des données de la page.

    • Tableau des tâches tasks.

  • 41 - 46 : Méthodes de la page.

    • deleteTask(index) supprime la tâche qui se situe à l'index passé en paramètre.

Passer des données à un composant via un <slot>

Une autre méthode pour passer des informations à un élément les <slots>.

On déclare dans le composant un espace <slot></slot> qui sera remplacé par le contenu saisi entre la balise d'ouverture et de fermeture d'un composant.

Exemple composant avec slot

L'exemple suivant décrit un composant <note> qui affiche le texte "Note : " devant le contenu du composant.

  • 4 : Ajout d'un slot au composant

    • Le contenu HTML saisi entre <note>...</note> sera injecté à la place de <slot></slot>

Dans une page on utilisera le composant Note ainsi :

  • 5 - 6 : création de deux composants <note>

  • 20 : importation du composant Note.vue

Les événements personnalisés pour communiquer aux parents

Le seul moyen pour un composant enfant de communiquer avec ses parents est de créer des événements personnalisés qui seront écoutés par leur parents.

Pour définir les évènements disponibles dans notre composant:

circle-info

defineEmits est une macro du compilateur; il n'y a pas besoin de l'importer

Pour déclencher un événement personnalisé dans le composant enfant :

Pour écouter un événement enfant depuis le parent

Exemple d'événement pour supprimer une tâche

Dans cet exemple afin de coller au mieux à la réalité, nous n'allons pas utiliser l'index du tableau pour supprimer une tâche, mais un identifiant unique id propre à la tâche, comme on le recevrais depuis une base de données.

Dans le composant components/Task.vue, nous allons supprimer la propriété index et dans le <template> remplacer deleteTask(index) par deleteTask(task.id).

  • 5 : remplacement deleteTask(index) par deleteTask(task.id).

  • 13 : suppression de la propriété index

Dans pages/Index.vue on a ajouté un id à toutes les tâches, retiré l'index de la boucle v-for, passé task.id comme :key et modifié la méthode deleteTask(id) pour quelle supprime la tâche avec l'id correspondant et non la tâche à l'index correspondant.

  • 5 : Suppression index de v-for

  • 6 : Passage de l'id de la tâche comme identifiant unique :key

  • 19, 25 et 31 : ajout d'un id à toutes les tâches

  • 38 - 40 : modification de la méthode deleteTask pour qu'elle supprime la tâche avec l'id correspondant à son paramètre.

circle-info

Ligne 39: task => task.id !== id

  • Ceci est bien une fonction à flèche

  • pas besoin de parenthèse si on n'a qu'un paramètre

  • on peut faire une fonction flèchée sans accolades, ce qui aura pour effet de retourner directement la valeur indiquée.

Ce code est donc équivalent à:

triangle-exclamation

En effet notre composant Task.vue fait appel à une méthode deleteTask qui lui est inconnue. Un composant ne peut seulement faire appel à ses propres méthodes, il ne peut donc pas appeler celles de son parent.

C'est là qu'interviennent les événements personnalisés.

  1. Au click du bouton de suppression, nous allons émettre un événement delete qui contiendra l'id de la tache à supprimer.

  2. Nous allons dire au parent d'écouter cet événement et d'appeler deleteTask lorsqu'il l'entendra.

  3. deleteTask récupèrera l'id et supprimera la tâche.

Dans components/Task.vue

  • 5 : au click, émission d'un événement delete contenant l'id de la tâche

  • 14 - 16: définition de l'évènement

Dans la page Index.vue

  • 8 : Ecoute de l'événement delete et appel de deleteTask lorsqu'il est entendu.

Et voilà ! Vous savez maintenant créer des composants et comment ils peuvent communiquer entre eux.

Mis à jour

Ce contenu vous a-t-il été utile ?