En effet, beforeRouteEnter en est un !
Navigation guards
Les navigation guards s'exécutent lorsqu'il y a un changement sur la route. Donc soit quand on arrive sur une route, soit quand on la quitte, soit quand il y a un changement d'attribut dynamique (beforeRouteEnter, beforeRouteLeave, beforeRouteUpdate). On peut ainsi se servir de beforeRouteEnter pour chaque route et vérifier si des conditions sont remplies pour afficher le composant par la suite.
Et pour ça, nous avons beforeEach. Une sorte de navigation guard qui exécuterait un beforeRouteEnter pour chaque route :) (il y a également afterEach pour beforeRouteLeave).
Ça a l'air super pratique !
Ça l'est ;).
Ok, donc ces navigation guards beforeEach et afterEach s'utilisent directement dans le router (index.js).
Pour simuler que quelqu'un est connecté, on imagine qu'on regarde dans le localStorage (ce qui est souvent le cas) si "auth" est à true.
La syntaxe d'un navigation guard ne t'est pas inconnue : c'est une fonction qui prend le fameux callback composé des paramètres to, from et next ;).
L'idée est simple. Si la personne n'est pas autorisée, on la redirige (grâce à next), sinon on la laisse passer (grâce à next aussi) :
{"language":"text/javascript","content":"const routes = [\n\t//....\n\t{\n \tpath: '/news/moderate',\n \tname: 'Moderation',\n \tcomponent: NewsModeration\n \t}\n]\n\nconst router = createRouter({\n history: createWebHistory(process.env.BASE_URL),\n routes\n})\n\nrouter.beforeEach((to, from, next)=>{\n if(to.name == 'Moderation' && !localStorage.getItem('auth')) {\n next({name:'Connexion'})\n } else {\n next()\n }\n})","filename":"index.js"}
Le vérifie que la page à laquelle on souhaite accéder a pour nom "Moderation". Si c'est le cas et qu'il n'y a pas auth=true dans le localStorage, alors on redirige vers login ;). Sinon on laisse passer.
C'est très pratique, mais ne vois-tu pas un inconvénient ?
Hum... Si j'ai 25 routes qui nécessitent l'authentification, je devrai mettre if(to.name === 'truc' or to.name=== 'machin'...) ? C'est long...
En effet, c'est pour ça qu'il y a une autre super fonctionnalité : les meta fields.
Les meta fields
Les meta fields sont des données personnalisées que tu peux mettre sur chaque route. Tu peux en mettre autant que tu veux, dans un objet appelé... meta ;).
On peut du coup y mettre une petite variable du style : routeQuiABesoinDauthentification:true
Et c'est ce que nous allons faire :
{"language":"text/javascript","content":"const routes = [\n\t//....\n\t{\n \tpath: '/news/moderate',\n \tname: 'Moderation',\n \tcomponent: NewsModeration,\n\t\tmeta: {\n\t\t\trequiresAuth:true\n\t\t}\n \t}\n]\n","filename":"index.js"}
Et ensuite, on n'a plus à vérifier le nom de chaque route, mais simplement si ce petit attribut est présent !
{"language":"text/javascript","content":"import { createRouter, createWebHistory } from 'vue-router'\nconst Home = () => import('../views/Home')\nconst Legals = () => import('../views/Legals')\nconst Connexion = () => import('../views/Connexion')\nconst News = () => import('../views/News')\nconst NewsAll = () => import('../views/NewsAll')\nconst NewsShow = () => import('../views/NewsShow')\nconst NewsModeration = () => import('../views/NewsModeration')\n\nconst routes = [\n {\n path: '/',\n name: 'Home',\n component: Home\n },\n {\n path: '/mentions-legales',\n name: 'Legals',\n component: Legals,\n },\n {\n path: '/connexion',\n name: 'Connexion',\n component: Connexion\n },\n {\n path: '/news',\n name: 'News',\n component: News,\n children: [\n {\n path: '',\n name: 'News.All',\n component: NewsAll,\n },\n {\n path: ':id(\\\\d+)',\n props:true,\n name: 'News.Show',\n component: NewsShow\n }\n ]\n },\n {\n path: '/news/moderate',\n name: 'Moderation',\n component: NewsModeration,\n meta:{\n requiresAuth:true\n }\n }\n]\n\nconst router = createRouter({\n history: createWebHistory(process.env.BASE_URL),\n routes\n})\n\nrouter.beforeEach((to, from, next)=>{\n if(to.meta.requiresAuth && !localStorage.getItem('auth')) {\n next({name:'Connexion'})\n } else {\n next()\n }\n})\n\nexport default router\n","filename":"index.js"}
C'est plus pratique !
Tu l'as dit ;)...
Tu commences déjà à savoir plein de choses avec vue-router ! Il nous reste 2-3 petites choses à voir uniquement... La prochaine étape est : les transitions. Hé oui, on peut aussi gérer des transitions entre chaque changement de page avec vue ;)
Je rappelle à toute fin utile que la sécurité côté frontend est une "utopie". Dans le cas d'une application réelle, où, par exemple, des données sensibles issues de votre backend sont récupérées par le frontend (via fetch par exemple) et que celles-ci doivent être visibles que des personnes connectées, ce n'est pas en utilisant les navigation guards que vous empêcherez une personne malintentionnée d'y accéder. En effet, il ne pourra pas voir la page, mais je rappelle que ce qui l'intéresse, ce sont les données. Et les données viennent de votre backend, récupérées via un appel API. S'il refait cet appel API à la main, dans ce cas, il a accès à ces données. Du coup, TOUJOURS protéger les données sensibles côtés back et authentifier les appels API (avec des [tokens JWT] par exemple).
J'ai terminé cette partie