Adloun

Vue : construire une application web (école d'ingénieur) · Chapitre 9 · Application directe du cours

D'un livre au suivant

Le routeur : plusieurs écrans, une seule page · niveau 2

Énoncé

Une fiche de livre affiche un lien « Livre suivant ». Voici une première version, où la fiche lit elle-même la route (props: false) :


<script setup>
import { RouterLink, useRoute } from "vue-router";
import { livres } from "./livres.js";

// Faux : lu une seule fois, à la création du composant.
const route = useRoute();
const rang = livres.findIndex((l) => l.isbn === route.params.isbn);
const livre = livres[rang];
const suivant = livres[(rang + 1) % livres.length];
</script>

<template>
  <h1>{{ livre.titre }}</h1>
  <RouterLink :to="{ name: 'livre', params: { isbn: suivant.isbn } }">
    Livre suivant
  </RouterLink>
</template>
  • On ouvre la fiche de Programmation Java, puis on clique deux fois sur « Livre suivant ». Prévoir l'adresse et le titre affiché après chaque clic.
  • Corriger le composant en recevant l'ISBN en prop.

Corrigé

  • Le test clique deux fois sur « Livre suivant », pour la version figée puis pour la version corrigée ci-dessous, et relève après chaque clic l'ISBN de l'adresse et le titre affiché :

figée : [
  'Programmation Java',
  '9782956300052 : Programmation Java',
  '9782956300052 : Programmation Java'
]
juste : [
  'Programmation Java',
  '9782956300052 : Le Petit Prince',
  '9782956300069 : L’Étranger'
]

Avec la version figée, le premier clic change bien l'adresse, mais le titre reste « Programmation Java » : le composant est réutilisé, et rang, livre, suivant ont été calculés une fois pour toutes à sa création. Le lien pointe donc toujours vers le Petit Prince, et le second clic ne mène nulle part de nouveau.

  • Avec props: true dans la route, l'ISBN arrive en prop, et des computed le suivent :

<script setup>
import { computed } from "vue";
import { RouterLink } from "vue-router";
import { livres } from "./livres.js";

// props: true dans la route : l'ISBN arrive en prop, et une prop est réactive.
const props = defineProps({ isbn: { type: String, required: true } });

const rang = computed(() => livres.findIndex((l) => l.isbn === props.isbn));
const livre = computed(() => livres[rang.value]);
const suivant = computed(() => livres[(rang.value + 1) % livres.length]);
</script>

<template>
  <h1>{{ livre.titre }}</h1>
  <RouterLink :to="{ name: 'livre', params: { isbn: suivant.isbn } }">
    Livre suivant
  </RouterLink>
</template>

Un computed sur useRoute().params.isbn conviendrait aussi ; c'est la lecture unique dans le <script setup> qui est fautive.

100 % gratuit

La suite du chapitre est sur Adloun

Exercice suivant et tuteur

Sans compte : le cours et le premier QCM. Exercices et tuteur : inscription gratuite en 30 secondes, sans carte bancaire.

Le cours du chapitre · Tous les exercices du chapitre

Exercice suivant et tuteur →