preface
The problem of dynamically rendering the sidebar based on user permissions is unavoidable when developing a background management system. After vue2.2.0, router.addroutes() can be used to addroutes dynamically.
router.addroutes()
use
addRoutes (routes: RouteConfig[]): void;
// Add more routing rules dynamically. The argument must be an array that matches the Routes option.
Copy the code
Easy to implement sidebar dynamic rendering:
Configure the static routing table in router.js:
export const constantRouterMap = [{
path: '/login'.component: () = > import('@/views/login/index'),
hidden: true
},]
Copy the code
Configure the routing table that needs to be dynamically rendered:
export const asyncRouterMap = [{
path: '/admin'.component: () = > import('@/views/admin/index'),
hidden: true.meta: {
title: 'xxx'.icon: 'xxx'.// Role permission field
role: ['admin']}}, {... }]Copy the code
BeforeEach (), obtain user information by performing operations in the navigator router.beforeeach (), obtain the role field based on the user information, compare it with asyncRouterMap[I].meta.role, and filter out the routing table to which the role belongs.
//permission.js
router.beforeEach(async (to, from, next) => {
// Verify that the user has logged in
const hasToken = getToken()
if (hasToken) {
if (to.path === '/login') {
// Whether to jump to the login page
next({
path: '/'})}else {
// This step is for routing data persistence to prevent abnormal display of the sidebar caused by vuEX data loss after refresh
const hasGetRouters = store.getters.routers
// Whether user information has been obtained
const hasGetUserInfo = store.getters.name
if (hasGetUserInfo && hasGetRouters.length) {
next()
} else {
try {
// Get role information
const {
role
} = await store.dispatch('user/getInfo')
// Pass in the role information and perform filtering
await store.dispatch('permission/getRoutes', {
role
})
// Dynamically add routesrouter.addRoutes(store.getters.addRouters); next({ ... to,replace: true})}catch (error) {
}
}
}
}
})
Copy the code
Some of the problems I encountered
You have successfully obtained the dynamic routing tablerouter.addRoutes()
Not afterthis.$router.options
The updated?
Actually, this is vue-Router design, In the issue the author mentioned That is normal, options is the object passed to the vuerouter constructor. It’s not modified afterwards. The route is already added, but the parameters are passed to the vuerouter constructor, so they are not visible in the vuerouter instance.
The sidebar if passedv-for="route in $router.options"
Render, how to achieve effective update?
As mentioned earlier, adding routes using router.addRoutes does not update this.$router.options, so the main implementation is to store the routing table through store.
//store
const state = {
routers: [].addRouters: []}const mutations = {
SET_ROUTERS: (state, routers) = > {
state.addRouters = routers;
// Join the static routing tablestate.routers = constantRouterMap.concat(routers); }}const actions = {
getRoutes({ commit }, data) {
return new Promise(resolve= > {
const{ role } = data; .// Filter out the routing table accessedRouters corresponding to the role
commit('SET_ROUTERS', accessedRouters); resolve(); }}})Copy the code
Use:
//sideBar.vue. mapState("permission", {
routers: "routers",}).Copy the code
Is the sidebar blank after refreshing?
Because vuex cannot persist data, the data is cleared after the page is refreshed, so you need to check whether the page is refreshed in route.beforeeach ().