In common background systems, there will be different user roles, such as super administrator, ordinary user, whose permissions are different, so the modules that can be manipulated or displayed are also not consistent. The following background management system framework is used as a template here
Address: https://github.com/PanJiaChen/vue-admin-template
Briefly speaking, the background menu is shown below, which requires that there are two types of users, administrators and ordinary employees in the system. Administrator login system can see all menu options, and ordinary users can only see the first menu items.
The Sidebar component code for the left menu of the project is as follows, configure this. $by traversing the current routing instance route with v-for. Router. Options. Routes are passed to <sidebar-item/> for demonstration, which is not detailed here.
<el-scrollbar wrap-class="scrollbar-wrapper"> <el-menu :default-active="activeMenu" :collapse="isCollapse" :background-color="variables.menuBg" :text-color="variables.menuText" :unique-opened="false" :active-text-color="variables.menuActiveText" :collapse-transition="false" mode="vertical" > <sidebar-item v-for="route in routes" :key="route.path" :item="route" :base-path="route.path" /> </el-menu> </el-scrollbar> <script> import { mapGetters } from 'vuex' import Logo from './Logo' import SidebarItem from './SidebarItem' export default { components: { SidebarItem, Logo }, computed: { ...mapGetters([ 'sidebar' ]), routes() { return this.$router.options.routes; }, } }
Thus, in order to display the menu bar dynamically, all the routing configuration objects in the project cannot be written together in the routing configuration file. Here, the routing configuration in the project is divided into three categories, as shown below. Constant Routes Constant Routes stores the routes visible to all users, including the home page, the login page, and 404 pages. asyncRoutes asynchronous routing, storing routes filtered out by different users; Any Routes, redirects to 404 pages when the path is wrong. This gives you the flexibility to handle routing configuration information.
router/index.js
export const constantRoutes = [ { path: '/login', component: () => import('@/views/login/index'), hidden: true }, { path: '/404', component: () => import('@/views/404'), hidden: true }, { path: '/', component: Layout, redirect: '/dashboard', children: [{ path: 'dashboard', name: 'Dashboard', component: () => import('@/views/dashboard/index'), meta: { title: 'home page', icon: 'dashboard' } }] }, ] export const asyncRoutes = [ { name: 'Acl', path: '/acl', component: Layout, redirect: '/acl/user/list', meta: { title: 'Rights Management', icon: 'el-icon-lock' }, children: [ { name: 'User', path: 'user/list', component: () => import('@/views/acl/user/list'), meta: { title: 'user management', }, }, ...... ] }, { path:'/product', component:Layout, name:'Product', meta: { title: 'Commodity Management', icon: 'el-icon-goods' }, children:[ { path:'tradeMark', name:'TradeMark', component:() => import('@/views/product/tradeMark'), meta:{title:'Brand Management'} }, ...... ] }, ]; export const anyRoutes = [ // 404 page must be placed at the end !!! { path: '*', redirect: '/404', hidden: true } ]; const createRouter = () => new Router({ // mode: 'history', // require service support scrollBehavior: () => ({ y: 0 }), routes: constantRoutes })
After a user logs in to the system, the browser retrieves the user's details based on the user's token information, which includes a list of menus (Array) that the user can access, as well as a list of buttons that the user can manipulate.
The request behavior occurs in vuex's actions, which are dispatched on the login page, and the responding user information is submitted to mutations in aciions.
const getDefaultState = () => { return { token: getToken(), name: '', avatar: '', routes:[], // Menu Tag Information Returned by Server buttons:[], // Button tag information returned by the server role:[], // Role information returned by the server } } const state = getDefaultState() const mutations = { RESET_STATE: (state) => { Object.assign(state, getDefaultState()) }, USER_INFO: (state,info) => { state.name = info.name; state.avator = info.avator; state.routes = info.routes; // Menu Permission Marker state.buttons = info.buttons; // Button Permission Marker state.role = info.role; // User role }, const actions = { // get user info getInfo({ commit, state }) { return new Promise((resolve, reject) => { getInfo(state.token).then(response => { const { data } = response if (!data) { return reject('Verification failed, please Login again.') } // commit('USER_INFO',data); resolve(data) }).catch(error => { reject(error) }) }) }, }
Once you have the displayable asynchronous routing flag information returned by the server, all you need to do next is to compare it with all the asynchronous routing information in the project to get the asynchronous routing information that you will ultimately need to show. Here, submit a mutations after you log in, named SEY_RESULTASYNCROUTES, passed to mutations a method computedAsyncRoutes, which compares the information of routes and returns the asynchronous routes that the current user wants to display as return values.
getInfo({ commit, state }) { return new Promise((resolve, reject) => { getInfo(state.token).then(response => { const { data } = response console.log(response.data); if (!data) { return reject('Verification failed, please Login again.') } // commit('USER_INFO',data); commit('SEY_RESULTASYNCROUTES',computedAsyncRoutes(asyncRoutes,data.routes)); resolve(data) }).catch(error => { reject(error) }) }) },
Define the computedAsyncRoutes method as follows, introduce asynchronous routing asyncRoutes, traverse the asyncRoutes array, compare the name of each route with the tag information routes passed from the server (indexOf method), and filter out the route information contained in the server tag array;
It is worth noting here that since there are secondary or even tertiary routes for routes, which are written in the children attribute of the route configuration object, they also need to be traversed and compared to determine whether they need to be displayed, and the computedAsyncRoutes method needs to be called recursively to filter each and routed children again.
import { resetRouter,asyncRoutes,anyRoutes,constantRoutes } from '@/router' // Compare the two arrays to figure out which asynchronous routes the current user is displaying const computedAsyncRoutes = (asyncRoutes,routes) => { return asyncRoutes.filter((item) => { // Routing information contained in the array returned by the server if(routes.indexOf(item.name) !== -1) { // If multilevel routing exists, recursively if(item.children && item.children.length) { item.children = computedAsyncRoutes(item.children,routes); } return true; } }) }
SEY_Submitted this way RESULTASYNCROUTES is a mutation in which you can get the routing configuration information asyncRoutes after processing, but you still need to do routing merge by merging the previously defined constant route, any route, and the newly filtered asynchronous route (array concat method) to form a final complete routing information. Add this routing rule router to the current project. AddRoutes (state.resultAllRoutes)
import router from '@/router' const getDefaultState = () => { return { token: getToken(), name: '', avatar: '', routes:[], // Menu Tag Information Returned by Server buttons:[], // Button tag information returned by the server role:[], // Role information returned by the server resultAsyncRoutes:[], resultAllRoutes:[] } } const state = getDefaultState(); mutations:{ // Final computed asynchronous routing SEY_RESULTASYNCROUTES(state,asyncRoutes){ // vuex saves asynchronous routes for the current user state.resultAsyncRoutes = asyncRoutes; // Calculate all routes for the current user state.resultAllRoutes = constantRoutes.concat(state.resultAsyncRoutes,anyRoutes); // Add a new route to a route router.addRoutes(state.resultAllRoutes); } }
At this time, the menu on the left side is still not displayed correctly after login.
Although the correct route already exists in the router instance at this time, the left navigation bar <Sidebar>component traversal still shows only the Home menu because of routes/index. Registering in JS is a constant route as shown below, while modifying the operation router.addRoutes(state.resultAllRoutes) are the result of an asynchronous operation and pass this. $in the sidebar component Router. Options. Routes can only get initial constant routes
router/index.js:
const createRouter = () => new Router({ // mode: 'history', // require service support scrollBehavior: () => ({ y: 0 }), routes: constantRoutes })
sidebar.vue
export default { components: { SidebarItem, Logo }, computed: { routes() { return this.$router.options.routes; }, } }
Simply change the access mode to the latest routing configuration information in the repository, this.$store.state.user.resultAllRoutes
sidebar.vue
routes() { return this.$store.state.user.resultAllRoutes; },
This achieves the effect of displaying different menus after users of different identities log in.
In addition, to achieve button permissions in the project, that is, the same button, some users display buttons, some users do not display buttons, as long as you get the above buttons array, use v-show on the corresponding button label to make a judgment.
<button v-show="$store.state.xxxModule.buttons.indexOf('Corresponding button label name')">delete</button>