Préambule
- L'objectif principal de ce TP est d'utiliser vue-router afin de mettre en place la "navigation" au sein de l'application.
1°/ Objectifs et contraintes
- Le code de différents composants va être modifié et d'autres composants vont être créés afin d'exploiter pleinement les possibilités de vue-router, notamment les routes multi-niveaux et les routes paramétrées.
- En premier lieu, la barre de navigation va être modifiée afin de suivre des routes au lieu de simplement renvoyer l'indice du bouton cliqué.
- Ensuite, le composant TownsView va être complètement remanié afin de pouvoir sélectionner de façon incrémentale une boutique en suivant des routes multi-niveaux et en créant des composants dédiés pour afficher des listes de rues et de boutiques.
- Enfin, le composant PersosView va être modifié pour gérer le contenu des slots avec un composant dédié, affiché grâce à une route multi-niveaux.
2°/ La barre de navigation
- L'objectif est d'intégrer directement le suivi des routes dans NavBar.
- Modifier router/index.js :
- la route /towns doit permettre d'afficher TownsView dans l'emplacement 'central'
- la route /persos doit permettre d'afficher PersosView dans l'emplacement 'central'
- Modifier le composant NavBar :
- les objets du tableau reçu en props contiennent maintenant un champ path,
- la valeur de path doit correspondre à une route définie dans router/index.js
- à la place, utiliser $router.push() afin de suivre la route associée au bouton.
- Modifier App :
- modifier le tableau passé en props à NavBar afin que les 2 objets de ce tableau contiennent un champ path dont la valeur correspond aux routes de niveau 1 /towns et /persos
- supprimer la méthode qui permet de suivre une route en fonction de l'index du bouton cliqué, ainsi que la variable index,
- modifier la balise <router-view> pour qu'elle affiche un composant dans l'emplacement 'central'
Remarque :
- Le fait d'intégrer le suivi de route directement dans NavBar est plus pertinent par rapport à la fonctionnalité du composant.
- En revanche, App perd la capacité de gérer le routage ou disons de faire quelque chose quand la route change, ce qui peut être gênant dans certains cas.
- C'est pourquoi, on laisse dans NavBar le principe d'émettre un événement en cas de clic sur un bouton. App peut toujours capturer l'événement et faire un traitement.
3°/ Refonte de TownsView
Remarques :
- les modifications suivantes se basent sur la solution des TPs 2 & 3.
- Les exercices proposés ci-dessous permettent de travailler sur vue-router en explorant ses possibilités.
- Il y a donc des questions qui pourraient être implémentées de façon différente (cf. remarques)
3.1°/ Objectifs
- Le principe est de faire la sélection d'une ville dans TownsView et quand elle a lieu, de suivre une route de niveau 2 pour afficher un composant StreetsView.
- Ce composant a une props qui contient l'id de la ville sélectionnée et peut donc aller chercher dans le store la liste des rues de la ville sélectionnée.
- StreetsView permet lui-même la sélection d'une rue et quand elle a lieu, de suivre une route de niveau 3 pour afficher un composant ShopsView.
- Ce composant a deux props contenant les id de la ville et de la rue sélectionnées, et peut donc aller chercher dans le store la liste des boutiques de la rue sélectionnée.
- Enfin, ShopsView permet de sélectionner une boutique, et quand elle a lieu, de modifier le store pour mettre à jour la "boutique courante".
- La boutique courante, si elle existe, est affichée en bas de TownsView (NB: sans passer par du routage, juste avec un v-if)
3.2°/ Mise en place
- Modifier TownsView :
- modifier le code de la balise <div> "à gauche", pour que la sélection de la ville courante se fasse grâce à une liste déroulante ou bien des boutons radio.
- quand l'utilisateur sélectionne une ville, cela permet de suivre une route de niveau 2 /towns/:idtown (cf. modification de router/index.js ci-dessous). Il faut bien entendu que idtown soit l'id de la ville sélectionnée.
- modifier le code de la balise <div> "à droite" afin qu'elle affiche avec <router-view> un composant dans l'emplacement 'streets'
- ajouter une balise <Shop> "en bas" du composant qui s'affiche uniquement si currentShop dans le store est différent de null.
- Créer StreetsView :
- le composant définit une props idTown, contenant l'id d'une ville.
- grâce à cet id, il récupère la liste des rues de cette ville et les affiche "à gauche" sous forme d'une liste déroulante ou bien de bouton radio.
- quand l'utilisateur sélectionne une rue, cela permet de suivre une route de niveau 3 /towns/:idtown/street/:idstreet (cf. modification de router/index.js ci-dessous). Il faut bien entendu que idstreet soit l'id de la rue sélectionnée.
- "à droite", le composant utilise <router-view> pour affiche un composant dans l'emplacement 'shops'
- Créer ShopsView :
- le composant définit deux props idTown et idStreet, contenant l'id d'une ville et d'une rue de cette ville.
- grâce à ces id, il récupère la liste des boutiques de la rue et les affiche "à gauche" sous forme d'une liste déroulante ou bien de bouton radio.
- quand l'utilisateur sélectionne une boutique, cela appelle une mutation du store pour mettre à jour la boutique courante.
- Modifier router/index.js :
- pour la route de niveau 1 /towns, ajouter en fils une route de niveau 2 :idtown permettant d'afficher le composant StreetsView à l'emplacement 'streets'
- pour cet emplacement 'streets', transformer le paramètre idtown en une props idTown.
- pour la route de niveau 2 /towns/:idtown, ajouter en fils une route de niveau 3 street/:idstreet permettant d'afficher le composant ShopsView à l'emplacement 'shops'
- pour cet emplacement 'shops', transformer les paramètres idtown et idstreet en des props idTown et idStreet.
- Après ces modifications, quand on sélectionne une ville, une rue, et une boutique, les composants StreetsView, ShopsView et Shop doivent tous être visibles.
- En revanche, si on sélectionne une nouvelle ville, ShopsView disparaît mais Shop reste visible : dans le store currentShop est toujours défini.
- Modifiez les composants pour que Shop disparaisse dès que l'on sélectionne une nouvelle ville et/ou rue.
Remarques :
- Le principe des routes multi-niveaux et des emplacements imbriqués conduit à certaines impossibilités de placement de composant sur la page de l'application.
- Par exemple, on pourrait faire une route de niveau 4 afin d'afficher la boutique sélectionnée. Le problème, c'est que son affichage se ferait obligatoirement DANS le composant ShopsView, qui permet de sélectionner une boutique, ce qui peut être nul d'un point de vue visuel.
- C'est pourquoi l'affichage de la boutique sélectionnée ne se fait pas grâce à du routage puisqu'on veut la placer "en bas" de TownsView.
- De façon similaire, si l'on voulait placer librement StreetsView et/ou ShopsView, on utiliserait plutôt des variables du store représentant la ville et rue courantes. Ces composants ne seraient affichés que si ces variables sont non null.
- En conclusion, le routage multi-niveaux n'est utile que si l'on veut afficher des composants routés imbriqués les uns dans les autres. Sinon, on utilise des variables du store pour indiquer si un composant est affiché ou non, ou bien on crée plusieurs routes de niveau 1 affichant plus ou moins de composants dans des emplacements de niveau 1 (donc pas imbriqués).
4°/ Refonte de PersosView
Remarques :
- les modifications suivantes se basent sur la solution des TPs 2 & 3.
4.1°/ Objectifs
- Contrairement à TownsView, on ne va pas utiliser le routage pour afficher un composant PersoCaracs décrivant un personnage sélectionné. En effet, on dispose déjà dans le store d'une variable représentant le personnage sélectionné.
- En revanche, le contenu des slots ne sera pas affiché directement, mais en suivant une route de niveau 2, permettant d'afficher un composant SlotEdit.
4.2°/ Mise en place
- Modifier PersosView :
- modifier le code de la balise <div> "à droite", pour afficher un composant PersoCaracs uniquement si la variable currentPerso dans le store est différente de null.
- déplacer les méthodes permettant de gérer les items (assignation/désassignation/revente) : cf. points suivants.
- Créer PersoCaracs :
- le composant affiche en gros les mêmes choses que dans les TPs précédents, excepté les slots qui apparaissent sous la forme de 5 boutons avec comme titre le nom du slot.
- le mécanisme du TP 4 permettant de revendre un item acheté doit également être présent.
- quand l'utilisateur clique sur un bouton, cela permet de suivre une route de niveau 2 /persos/slot/:name (cf. modification de router/index.js ci-dessous). Il faut bien entendu que name soit le nom du slot cliqué
- "en bas", le composant utilise <router-view> pour affiche un composant dans l'emplacement 'slot'
- Créer SlotEdit :
- le composant définit une props slotName, contenant le nom d'un slot
- grâce à ce nom, il récupère la liste des items assignés au slot pour le personnage courant et les affiche.
- le mécanisme du TP 4 permettant de désassigner un item doit être présent.
- Modifier router/index.js :
- pour la route de niveau 1 /persos, ajouter en fils une route de niveau 2 slot/:name permettant d'afficher le composant SlotEdit à l'emplacement 'slot'
- pour cet emplacement 'slot', transformer le paramètre name en une props slotName.
- Après ces modifications, il reste une fonctionnalité à implémenter : assigner un item à un slot.
- Il existe plusieurs solutions mais deux seulement doivent être implémentées :
- v1 : le composant SlotEdit a accès au personnage courant donc à la liste des items achetés. En fonction du slot, il peut créer une liste des items assignables au slot, (qui peut être vide à cause du type des items et/ou des limites du slot). Il affiche cette liste ainsi qu'un moyen d'assigner ses items au slot.
- v2 : le composant PersoCaracs calcule la liste des items assignables au slot courant (s'il existe), l'affiche, ainsi que le moyen d'assignation. En revanche, cela suppose qu'il connaisse le slot courant. A vous de trouver une solution.