Home > Article > Web Front-end > How to load the permission management module (detailed tutorial)
This article explains in detail how to dynamically load VUE components in the permission management module. Friends who have needs in this regard can follow along and learn.
In this article we will mainly talk about login and dynamic loading of components.
Save login status
After the user successfully logs in, the current user's login information needs to be saved locally for later use. The specific implementation is as follows:
Successfully log in and save data
After the login operation is successfully executed, the data is submitted to the store through the commit operation. The core code is as follows:
this.postRequest('/login', { username: this.loginForm.username, password: this.loginForm.password }).then(resp=> { if (resp && resp.status == 200) { var data = resp.data; _this.$store.commit('login', data.msg); var path = _this.$route.query.redirect; _this.$router.replace({path: path == '/' || path == undefined ? '/home' : path}); } });
store
The core code of store is as follows:
export default new Vuex.Store({ state: { user: { name: window.localStorage.getItem('user' || '[]') == null ? '未登录' : JSON.parse(window.localStorage.getItem('user' || '[]')).name, userface: window.localStorage.getItem('user' || '[]') == null ? '' : JSON.parse(window.localStorage.getItem('user' || '[]')).userface } }, mutations: { login(state, user){ state.user = user; window.localStorage.setItem('user', JSON.stringify(user)); }, logout(state){ window.localStorage.removeItem('user'); } } });
In order to reduce trouble, the data after the user successfully logs in will be saved in localStorage (to prevent the user from pressing Data is lost after F5 refresh), it is stored in the form of a string, and then converted to json when retrieved. When the user logs out, clear the data in localStorage.
Dynamic loading of components
In the permission management module, this is the core of the front-end.
Core idea
After the user successfully logs in, before entering the home page, the user sends a request to the server to obtain the current menu information and component information. The server will The role that the current user has and the resources corresponding to the role return a json string with the following format:
[ { "id": 2, "path": "/home", "component": "Home", "name": "员工资料", "iconCls": "fa fa-user-circle-o", "children": [ { "id": null, "path": "/emp/basic", "component": "EmpBasic", "name": "基本资料", "iconCls": null, "children": [], "meta": { "keepAlive": false, "requireAuth": true } }, { "id": null, "path": "/emp/adv", "component": "EmpAdv", "name": "高级资料", "iconCls": null, "children": [], "meta": { "keepAlive": false, "requireAuth": true } } ], "meta": { "keepAlive": false, "requireAuth": true } } ]
After the front end gets this string, it does two things: 1. Dynamically add json to the current route; 2. Save the data to the store, and then each page renders the menu based on the data in the store.
The core idea is not difficult. Let’s take a look at the implementation steps.
Data request timing
This is very important.
Some friends may ask why this is so difficult. Can’t I just request it after logging in successfully? Yes, it is possible to request menu resources after successful login. After the request is received, we will save it in the store for next time use. However, there will be another problem. If the user clicks on a certain sub-child after successfully logging in, Page, enter the sub-page, and then press F5 to refresh. At this time, it is GG, because the data in the store is gone after F5 is refreshed, and we only requested the menu resources once when the login is successful. There are two ideas to solve this problem: 1. Don’t save the menu resources to the store, but save them to localStorage, so that the data is still there even after F5 refreshes; 2. Directly in the mounted method of each page, go Load menu resources once.
Since the menu resources are very sensitive, it is best not to save them locally, so I abandoned option 1. However, the workload of option 2 is a bit heavy, so I took a step to simplify it. Just use the navigation guard in routing.
Routing Navigation Guard
My specific implementation is as follows. First, create a routes array in the store, which is an empty array, and then enable the global routing guard, as follows:
router.beforeEach((to, from, next)=> { if (to.name == 'Login') { next(); return; } var name = store.state.user.name; if (name == '未登录') { if (to.meta.requireAuth || to.name == null) { next({path: '/', query: {redirect: to.path}}) } else { next(); } } else { initMenu(router, store); next(); } } )
The code here is very short, let me give a simple explanation:
1. If the page you want to go to is the login page, there is nothing to say about this, just go through it.
2. If it is not a login page, I first get the current login status from the store. If not logged in, use the requireAuth attribute of the meta attribute in the routing to determine whether the page I want to go to requires login. If login is required, , then jump back to the login page, and at the same time pass the path of the page you want to go to as a parameter to the login page, so that you can jump to the target page after successful login. If you do not need to log in, go directly (in fact, there is only the Login page in this project No login required); if you are already logged in, initialize the menu first and then jump.
The operation of the initialization menu is as follows:
export const initMenu = (router, store)=> { if (store.state.routes.length > 0) { return; } getRequest("/config/sysmenu").then(resp=> { if (resp && resp.status == 200) { var fmtRoutes = formatRoutes(resp.data); router.addRoutes(fmtRoutes); store.commit('initMenu', fmtRoutes); } }) } export const formatRoutes = (routes)=> { let fmRoutes = []; routes.forEach(router=> { let { path, component, name, meta, iconCls, children } = router; if (children && children instanceof Array) { children = formatRoutes(children); } let fmRouter = { path: path, component(resolve){ if (component.startsWith("Home")) { require(['../components/' + component + '.vue'], resolve) } else if (component.startsWith("Emp")) { require(['../components/emp/' + component + '.vue'], resolve) } else if (component.startsWith("Per")) { require(['../components/personnel/' + component + '.vue'], resolve) } else if (component.startsWith("Sal")) { require(['../components/salary/' + component + '.vue'], resolve) } else if (component.startsWith("Sta")) { require(['../components/statistics/' + component + '.vue'], resolve) } else if (component.startsWith("Sys")) { require(['../components/system/' + component + '.vue'], resolve) } }, name: name, iconCls: iconCls, meta: meta, children: children }; fmRoutes.push(fmRouter); }) return fmRoutes; }
In the initialization menu, first determine whether the data in the store exists. If it exists, it means that this jump is a normal jump, not the user Press F5 or enter an address directly in the address bar. Otherwise go to the loading menu. After getting the menu, first use the formatRoutes method to convert the json returned by the server into the format required by the router. Here we mainly convert component, because the component returned by the server is a string, but what is needed in the router is a component, so we Just load the required components dynamically in the formatRoutes method. After the data format is successfully prepared, on the one hand, the data is stored in the store, and on the other hand, the addRoutes method in the routing is used to dynamically add it to the routing.
Menu rendering
Finally, in the Home page, get the menu json from the store and render it into a menu. The relevant code can be viewed in Home.vue. No need to go into details.
OK, after this, different users can see different menus after successfully logging in.
The above is what I compiled for everyone. I hope it will be helpful to everyone in the future.
Related articles:
How to get the value in select in vue.js (detailed tutorial)
In Vue2.0 How to use filters in series?
How to return to the top through the tween method in the vue project
How to use vue to determine that the input content is all spaces?
How to use js to determine that the input box cannot be a space or null value?
The above is the detailed content of How to load the permission management module (detailed tutorial). For more information, please follow other related articles on the PHP Chinese website!