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.optionsThe 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 ().