Maison > Article > interface Web > Explication détaillée du chargement dynamique des instances de composants Vue dans le module de gestion des autorisations
Cette série d'articles n'est pas un didacticiel étape par étape. Elle présente principalement les idées de base et explique le code de base. Les amis peuvent mettre en vedette et cloner le code complet sur GitHub pour l'étudier. De plus, j'avais initialement prévu de lancer le projet et de le mettre en ligne pour que des amis puissent le voir, mais afin d'économiser de l'argent avant d'acheter un serveur, la mémoire n'était que de 512 Mo et les deux applications ne pouvaient pas fonctionner (il existe déjà un V Tribe projet open source en cours d'exécution), donc mes amis, nous ne pouvons regarder que la capture d'écran ci-dessous. Il existe un didacticiel de déploiement sur GitHub. Vous pouvez également le déployer localement pour voir l'effet complet.
Adresse du projet : https://github.com/lenve/vhr
Nous avons essentiellement résolu les articles précédents Cela résout problèmes côté serveur et encapsule les requêtes frontales. Dans cet article, nous parlons principalement de connexion et de chargement dynamique des composants.
Cet article est le cinquième de cette série. Il est recommandé de lire d'abord les articles précédents pour vous aider à mieux comprendre cet article :
1. SpringBoot+Vue sépare le front-end et le back-end et utilise SpringSecurity pour gérer parfaitement les problèmes d'autorisation (1)
2 SpringBoot+Vue sépare le front-end et le back-end et utilise SpringSecurity pour gérer parfaitement les problèmes d'autorisation (2) <.>3. Salage de mot de passe dans SpringSecurity et SpringBoot Gestion unifiée des exceptions
4.axios encapsulation des demandes et gestion unifiée des exceptions
Lorsque l'utilisateur se connecte avec succès, il doit le faire. Les informations de connexion de l'utilisateur actuel sont enregistrées localement pour une utilisation ultérieure. La mise en œuvre spécifique est la suivante :
Une fois l'opération de connexion exécutée avec succès, les données sont soumises au store via l'opération de validation.Le noyauLe code est le suivant :
<span style="font-size: 14px;">this.postRequest('/login', {<br> username: this.loginForm.username,<br> password: this.loginForm.password<br>}).then(resp=> {<br> if (resp && resp.status == 200) {<br> var data = resp.data;<br> _this.$store.commit('login', data.msg);<br> var path = _this.$route.query.redirect;<br> _this.$router.replace({path: path == '/' || path == undefined ? '/home' : path});<br> }<br>});<br></span>
Le code principal du magasin est le suivant :
<span style="font-size: 14px;">export default new Vuex.Store({<br> state: {<br> user: {<br> name: window.localStorage.getItem('user' || '[]') == null ? '未登录' : JSON.parse(window.localStorage.getItem('user' || '[]')).name,<br> userface: window.localStorage.getItem('user' || '[]') == null ? '' : JSON.parse(window.localStorage.getItem('user' || '[]')).userface<br> }<br> },<br> mutations: {<br> login(state, user){<br> state.user = user;<br> window.localStorage.setItem('user', JSON.stringify(user));<br> },<br> logout(state){<br> window.localStorage.removeItem('user');<br> }<br> }<br>});<br></span>
Afin de réduire les problèmes, les données une fois que l'utilisateur s'est connecté avec succès seront enregistrées dans localStorage (pour éviter la perte de données après que l'utilisateur appuie sur F5 pour actualiser), stockées sous la forme d'une chaîne, puis converti en json une fois récupéré. Lorsque l'utilisateur se déconnecte, effacez les données dans localStorage.
Dans le module de gestion des autorisations, c'est le cœur du front-end.
Une fois que l'utilisateur s'est connecté avec succès, avant d'accéder à la page d'accueil, l'utilisateur envoie une requête au serveur pour obtenir le informations du menu actuel et Pour les informations sur les composants, le serveur renvoie une chaîne json basée sur le rôle de l'utilisateur actuel et les ressources correspondant au rôle. Le format est le suivant :
<span style="font-size: 14px;">[<br> {<br> "id": 2,<br> "path": "/home",<br> "component": "Home",<br> "name": "员工资料",<br> "iconCls": "fa fa-user-circle-o",<br> "children": [<br> {<br> "id": null,<br> "path": "/emp/basic",<br> "component": "EmpBasic",<br> "name": "基本资料",<br> "iconCls": null,<br> "children": [],<br> "meta": {<br> "keepAlive": false,<br> "requireAuth": true<br> }<br> },<br> {<br> "id": null,<br> "path": "/emp/adv",<br> "component": "EmpAdv",<br> "name": "高级资料",<br> "iconCls": null,<br> "children": [],<br> "meta": {<br> "keepAlive": false,<br> "requireAuth": true<br> }<br> }<br> ],<br> "meta": {<br> "keepAlive": false,<br> "requireAuth": true<br> }<br> }<br>]<br></span>Le frontal obtient ce caractère Après la chaîne, faites deux choses : 1. Ajoutez dynamiquement json à l'itinéraire actuel 2. Enregistrez les données dans le magasin, puis chaque page affiche le menu en fonction des données du magasin ;
L'idée de base n'est pas difficile. Jetons un coup d'œil aux étapes de mise en œuvre.
Délai de demande de données
Certains amis peuvent me demander pourquoi c'est si difficile. Puis-je simplement le demander après m'être connecté avec succès ? Oui, il est possible de demander des ressources de menu après une connexion réussie. Une fois la demande reçue, nous la sauvegarderons dans le magasin pour une prochaine utilisation. Cependant, il y aura un autre problème si l'utilisateur clique ensuite sur un certain sous-enfant. Connectez-vous avec succès, Page, entrez dans la sous-page, puis appuyez sur F5 pour actualiser. À ce moment-là, il s'agit de GG, car les données du magasin ont disparu après l'actualisation de F5, et nous n'avons demandé les ressources du menu qu'une seule fois. la connexion est réussie. Il y a deux idées pour résoudre ce problème : 1. Ne pas enregistrer les ressources du menu dans le magasin, mais les enregistrer dans localStorage, afin que les données soient toujours là même après l'actualisation de F5. 2. Directement dans le fichier monté ; méthode de chaque page, allez Charger les ressources du menu une fois.
Les ressources du menu étant très sensibles, il est préférable de ne pas les sauvegarder localement, j'ai donc abandonné l'option 1, mais l'option 2 est une charge de travail un peu lourde, j'ai donc fait un pas pour sauvegarder localement. La façon de le simplifier est d'utiliser la garde de navigation dans le routage.
Route Navigation Guard
<span style="font-size: 14px;">router.beforeEach((to, from, next)=> {<br> if (to.name == 'Login') {<br> next();<br> return;<br> }<br> var name = store.state.user.name;<br> if (name == '未登录') {<br> if (to.meta.requireAuth || to.name == null) {<br> next({path: '/', query: {redirect: to.path}})<br> } else {<br> next();<br> }<br> } else {<br> initMenu(router, store);<br> next();<br> }<br> }<br>)<br></span>Le code ici est très court, laissez-moi vous donner une explication simple :
Si la page que vous souhaitez consulter. allez sur la page de connexion, il n'y a rien à dire à ce sujet, allez-y. 2.如果不是登录页面的话,我先从store中获取当前的登录状态,如果未登录,则通过路由中meta属性的requireAuth属性判断要去的页面是否需要登录,如果需要登录,则跳回登录页面,同时将要去的页面的path作为参数传给登录页面,以便在登录成功之后跳转到目标页面,如果不需要登录,则直接过(事实上,本项目中只有Login页面不需要登录);如果已经登录了,则先初始化菜单,再跳转。 初始化菜单的操作如下: 在初始化菜单中,首先判断store中的数据是否存在,如果存在,说明这次跳转是正常的跳转,而不是用户按F5或者直接在地址栏输入某个地址进入的。否则就去加载菜单。拿到菜单之后,首先通过formatRoutes方法将服务器返回的json转为router需要的格式,这里主要是转component,因为服务端返回的component是一个字符串,而router中需要的却是一个组件,因此我们在formatRoutes方法中动态的加载需要的组件即可。数据格式准备成功之后,一方面将数据存到store中,另一方面利用路由中的addRoutes方法将之动态添加到路由中。 最后,在Home页中,从store中获取菜单json,渲染成菜单即可,相关代码可以在 OK,如此之后,不同用户登录成功之后就可以看到不同的菜单了。 相关推荐:<span style="font-size: 14px;">export const initMenu = (router, store)=> {<br> if (store.state.routes.length > 0) {<br> return;<br> }<br> getRequest("/config/sysmenu").then(resp=> {<br> if (resp && resp.status == 200) {<br> var fmtRoutes = formatRoutes(resp.data);<br> router.addRoutes(fmtRoutes);<br> store.commit('initMenu', fmtRoutes);<br> }<br> })<br>}<br>export const formatRoutes = (routes)=> {<br> let fmRoutes = [];<br> routes.forEach(router=> {<br> let {<br> path,<br> component,<br> name,<br> meta,<br> iconCls,<br> children<br> } = router;<br> if (children && children instanceof Array) {<br> children = formatRoutes(children);<br> }<br> let fmRouter = {<br> path: path,<br> component(resolve){<br> if (component.startsWith("Home")) {<br> require(['../components/' + component + '.vue'], resolve)<br> } else if (component.startsWith("Emp")) {<br> require(['../components/emp/' + component + '.vue'], resolve)<br> } else if (component.startsWith("Per")) {<br> require(['../components/personnel/' + component + '.vue'], resolve)<br> } else if (component.startsWith("Sal")) {<br> require(['../components/salary/' + component + '.vue'], resolve)<br> } else if (component.startsWith("Sta")) {<br> require(['../components/statistics/' + component + '.vue'], resolve)<br> } else if (component.startsWith("Sys")) {<br> require(['../components/system/' + component + '.vue'], resolve)<br> }<br> },<br> name: name,<br> iconCls: iconCls,<br> meta: meta,<br> children: children<br> };<br> fmRoutes.push(fmRouter);<br> })<br> return fmRoutes;<br>}<br></span>
菜单渲染
<span style="font-size: 14px;">Home.vue</span>
中查看,不赘述。
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!