Étape 17 — Transposition projet personnel
Objectif
Appliquer les concepts de la séquence 5 (favoris + persistance) à votre projet individuel.
Ce que vous avez appris
| Concept | Pokédex | Votre projet |
|---|---|---|
localStorage | Sauvegarder les IDs des Pokémon favoris | Sauvegarder les préférences/favoris de l'utilisateur |
JSON.stringify() / JSON.parse() | Convertir un tableau d'IDs en string et vice-versa | Stocker n'importe quelle donnée structurée |
State favorites | Tableau d'IDs dans le store Pinia | Votre propre liste de favoris/sélections |
| Getter avec paramètre | isFavorite(pokemon) retourne true/false | Vérifier un état pour un élément donné |
| Getter calculé | getFavorites transforme des IDs en objets | Dériver des données complexes depuis le state |
Action toggle | Ajoute ou retire un favori en un clic | Tout bouton on/off dans votre application |
@click.stop.prevent | Empêcher la navigation quand on clique sur le coeur | Tout bouton à l'intérieur d'un élément cliquable |
v-if / v-else | Alerte "aucun favori" ou grille de cartes | Affichage conditionnel selon l'état des données |
| Réutilisation de composant | PokemonCard dans la page d'accueil ET la page favoris | Un composant = un usage dans plusieurs contextes |
Checklist projet perso
Avant de quitter, vérifiez que votre projet individuel a :
- Un state
favorites(ou équivalent) dans le store — tableau d'IDs - Une action
toggleFavorite()qui ajoute ou retire un élément - Une action
saveFavorites()qui persiste danslocalStorage - Une action
loadFavorites()appelée dansinit()du store - Un getter
isFavorite()utilisé pour changer l'apparence du bouton - Un getter
getFavoritesqui retourne les objets complets (pas juste les IDs) - Un bouton favori avec
@click.stop.prevent(si le parent est cliquable) - Une page dédiée aux favoris avec un message "aucun favori" si la liste est vide
- Les favoris persistent après rechargement de la page
- Le composant carte est réutilisé sur la page d'accueil ET la page favoris
- 0 erreurs dans la console
- Commit poussé sur GitHub
- Version en ligne vérifiée (Vercel ou GitHub Pages)
Prochaine séquence
La semaine prochaine, on ajoutera un formulaire d'ajout de Pokémon avec validation. Préparez-vous à comprendre :
v-modelsur différents types de champs (texte, select, nombre)- Validation de formulaire avec les règles Vuetify
@submit.preventpour empêcher le rechargement de la page- Requête POST vers l'API
Préparation oral — Concepts clés de la séquence 5
Questions que vous devez savoir expliquer :
Pourquoi stocker des IDs plutôt que des objets complets dans les favoris ? Les IDs sont légers (une string) et stables. Les objets peuvent changer (niveau, stats...). On retrouve l'objet complet via
pokemons.find(). Stocker des objets danslocalStorageprendrait beaucoup plus de place et pourrait devenir obsolète.Qu'est-ce que
localStorageet quelles sont ses limites ? C'est un espace de stockage dans le navigateur (~5 Mo) qui persiste même après fermeture. Il ne stocke que des strings — d'oùJSON.stringify/parse. Il est synchrone (bloque le thread) et non sécurisé (tout script de la page peut y accéder). Il ne remplace pas une base de données.Pourquoi
@click.stop.preventet pas juste@click? Parce que le bouton coeur est à l'intérieur d'un<v-card :to="...">qui agit comme un lien. Sans.stop, le clic remonte au parent (<v-card>) qui déclenche la navigation. Sans.prevent, le comportement par défaut du<router-link>s'exécute quand même.Qu'est-ce qu'un getter avec paramètre dans Pinia ? C'est un getter qui retourne une fonction au lieu d'une valeur. On l'appelle avec un argument :
isFavorite(pokemon). Ça permet de vérifier une condition pour un élément spécifique, pas juste pour l'état global.Pourquoi
getFavoritesutilise.filter(p => p !== undefined)? Parce qu'un favori peut référencer un Pokémon qui a été supprimé de l'API.find()retourneraitundefinedpour cet ID. Le.filter()nettoie ces cas pour éviter des erreurs dans le template (Cannot read property 'name' of undefined).Quelle est la différence entre
.stopet.prevent?.stopappelleevent.stopPropagation()— empêche l'événement de remonter aux éléments parents..preventappelleevent.preventDefault()— empêche le comportement natif de l'élément (navigation d'un lien, soumission d'un formulaire, etc.). Ce sont deux mécanismes indépendants.Qu'est-ce que le pattern toggle ? C'est un pattern où une seule action fait deux choses opposées selon l'état actuel : si l'élément est dans la liste, on le retire ; sinon, on l'ajoute. Dans le Pokédex,
toggleFavorite()vérifie si l'ID existe déjà dansfavorites— si oui,splicepour retirer, sinonpushpour ajouter. Un seul bouton, deux comportements.