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: truedans la route, l'ISBN arrive en prop, et descomputedle 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
- 10 autres exercices corrigés dans ce chapitre
- Les 2 QCM du chapitre, le premier sans compte
- Le tuteur, qui guide pas à pas sans donner la réponse
Sans compte : le cours et le premier QCM. Exercices et tuteur : inscription gratuite en 30 secondes, sans carte bancaire.