About dynamically adding routes based on user permissions in Vue

About dynamically adding routes based on user permissions in Vue

Display different menu pages according to the user's permissions.

Knowledge Points

Route guard (using pre-guard): determine which routes to add based on user roles
vuex: save dynamically added routes

difficulty

The route guard needs to be called every time the route changes, and the data in the store will be cleared every time it is refreshed, so it is necessary to determine whether there are any dynamic routes added to the store.
(If there is no judgment, it will continue to add and cause memory overflow)

insert image description here

Determine the route based on the role and filter the dynamic route to determine whether the role of each route is consistent with the role passed in at login

insert image description here

<template>
  <div>
    <el-menu
      :default-active="$route.path"
      class="el-menu-vertical-demo menu_wrap"
      background-color="#324057"
      text-color="white"
      active-text-color="#20a0ff"
      :collapse="isCollapse"
      unique-opened
      router
    >
      <el-submenu
        v-for="item in $store.state.Routers"
        :key="item.path"
        :index="item.path"
        v-if="!item.hidden"
      >
        <template slot="title" >
          <i class="el-icon-location"></i>
          <span>{{ item.meta.title }}</span>
        </template>
        <div v-for="chi in item.children" :key="chi.name">
          <el-menu-item v-if="!chi.hidden" :index="item.path + '/' + chi.path">
            <i class="el-icon-location"></i>{{ chi.meta.title }}
          </el-menu-item>
        </div>
      </el-submenu>
    </el-menu>
  </div>
</template>

<script>
export default {
  name: "MenuList",
  data() {
    return {
      isCollapse: false,
    };
  },
  created() {
    this.$bus.$on("getColl", (data) => {
      this.isCollapse = data;
    });
  },
  methods: {

  }
};
</script>

<style scoped>
.menu_wrap {
  height: 100vh;
}
.el-menu-vertical-demo:not(.el-menu--collapse) {
  width: 200px;
  height: 100vh;
}
</style>
import Vue from 'vue'
import VueRouter from 'vue-router'
import store from '../store/index'

Vue.use(VueRouter)

const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push(location) {
  return originalPush.call(this, location).catch(err => err)
}

export const routes = [
  {
    path: '/home',
    name: 'First',
    component: () => import('../views/Index.vue'),
    meta: { title: 'Home'},
    children: [
      {
        path: 'index',
        name: 'Home',
        component: () => import('../views/Home'),
        meta: { title: 'Home', roles: ['Customer'] }
      }
    ]
  },
  {
    path: '/index',
    name: 'NavigationOne',
    component: () => import('../views/Index.vue'),
    meta: { title: 'Navigation 1'},
    children: [
      {
        path: 'personnel',
        name: 'Personnel ',
        component: () => import('../views/One/Personnel.vue'),
        meta: { title: 'Personnel', roles: ['Customer'] }
      },
      {
        path: 'account',
        name: 'Account',
        component: () => import('../views/One/Account.vue'),
        meta: { title: 'Account', roles: ['Customer'] }
      },
      {
        path: 'psw',
        name: 'psw',
        component: () => import('../views/One/Password.vue'),
        meta: { title: 'psw', roles: ['Customer'] }
      }
    ]
  },
  {
    path: '/card',
    name: 'NavigationTwo',
    component: () => import('../views/Index.vue'),
    meta: { title: 'Navigation 2'},
    children: [
      {
        path: 'activity',
        name: 'Activity',
        component: () => import('../views/Three/Activity.vue'),
        meta: { title: 'Activity', roles: ['Customer'] }
      },
      {
        path: 'Social',
        name: 'Social',
        component: () => import('../views/Three/Social.vue'),
        meta: { title: 'Social', roles: ['Customer'] }
      },
      {
        path: 'content',
        name: 'Content',
        component: () => import('../views/Three/Content.vue'),
        meta: { title: 'Content', roles: ['Customer'] }
      }
    ]
  },
  {
    path: '/two',
    name: 'NavigationThree',
    component: () => import('../views/Index.vue'),
    meta: { title: 'Navigation 3'},
    children: [
      {
        path: 'index',
        name: 'Two',
        component: () => import('../views/Two'),
        meta: { title: 'Two', roles: ['Customer'] }
      }]
  },
  {
    path: '/404',
    name: 'Error',
    hidden: true,
    meta: { title: 'error'},
    component: () => import('../views/Error')
  }
]

export const asyncRouter = [
  //Agent3 Staff2
  {
    path: '/agent',
    component: () => import('../views/Index.vue'),
    name: 'Agent',
    meta: { title: 'Agent', roles: ['Agent', 'Staff']},
    children: [
      {
        path: 'one',
        name: 'agentOne',
        component: () => import('@/views/agent/One'),
        meta: { title: 'agentOne', roles: ['Agent', 'Staff'] }
      },
      {
        path: 'two',
        name: 'agentTwo',
        component: () => import('@/views/agent/Two'),
        meta: { title: 'agentTwo', roles: ['Agent'] }
      },
      {
        path: 'three',
        name: 'agentThree',
        component: () => import('@/views/agent/Three'),
        meta: { title: 'agentThree', roles: ['Agent', 'Staff'] }
      }
    ]
  },
  //Staff3
  {
    path: '/staff',
    component: () => import('../views/Index.vue'),
    name: 'Staff',
    meta: { title: 'Staff', roles: ['Staff']},
    children: [
      {
        path: 'one',
        name: 'StaffOne',
        component: () => import('@/views/Staff/One'),
        meta: { title: 'StaffOne', roles: ['Staff'] }
      },
      {
        path: 'two',
        name: 'StaffTwo',
        component: () => import('@/views/Staff/Two'),
        meta: { title: 'StaffTwo', roles: ['Staff'] }
      },
      {
        path: 'three',
        name: 'StaffThree',
        component: () => import('@/views/Staff/Three'),
        meta: { title: 'StaffThree', roles: ['Staff'] }
      }
    ]
  },
  { path: '*', redirect: '/404', hidden: true }
]

const router = new VueRouter({
  routes
})


router.beforeEach((to, from, next) => {
  let roles = ['Staff']
  if(store.state.Routers.length) {
    console.log('yes')
    next()
  } else {
    console.log('not')
    store.dispatch('asyncGetRouter', {roles})
    .then(res => {
      router.addRoutes(store.state.addRouters)
    })
    next({...to})
    // The difference between next() and next({ ...to }): next() allows next('/XXX') to intercept infinitely}
})

export default router

import Vue from 'vue'
import Vuex from 'vuex'
import modules from './module'

import router, {routes, asyncRouter} from '../router'

function hasPermission(route, roles) {
  if (route.meta && route.meta.roles) {
    return roles.some(role => route.meta.roles.indexOf(role) >= 0)
  } else {
    return true
  }
  
}

/*
  Recursively filter the asynchronous routing table to return routes that match the user role @param asyncRouter asynchronous routing @param roles user role*/
function filterAsyncRouter(asyncRouter, roles) {
  let filterRouter = asyncRouter.filter(route =>{
    if (hasPermission (route, roles)) {
      if (route.children && route.children.length) {
          route.children = filterAsyncRouter(route.children, roles)
      }
      return true 
    }
    return false
  })
  return filterRouter
}

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    addRouters: [],
    Routers: []
  },
  mutations:
    getRouter(state, paload) {
      // console.log(paload)
      state.Routers = routes.concat(paload)
      state.addRouters = paload
      // router.addRoutes(paload)
    }
  },
  actions: {
    asyncGetRouter({ commit }, data) {
      const { roles } = data
      return new Promise(resolve => {
        let addAsyncRouters = filterAsyncRouter(asyncRouter, roles)
        commit('getRouter', addAsyncRouters)
        resolve()
      })
    }
  }
})

This is the end of this article about the detailed explanation of dynamically adding routes according to user permissions in Vue. For more relevant Vue dynamic adding routes content, please search for previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope everyone will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Vue implements permission control routing (vue-router dynamically adds routing)
  • Vue dynamic addition of routing and generation of menu method example
  • Vue dynamically adds routes addRoutes and cannot store dynamic routes in the cache
  • vue solves the problem of refresh failure after dynamically adding routes in addRoutes
  • Vuex displays different routing list functions according to different user permissions
  • Vue-Access-Control front-end user permission control solution

<<:  wget downloads the entire website (whole subdirectory) or a specific directory

>>:  The difference between shtml and html

Recommend

JavaScript simulation calculator

This article shares the specific code of JavaScri...

How to uninstall MySQL 5.7.19 under Linux

1. Find out whether MySQL was installed before Co...

Pure CSS custom multi-line ellipsis problem (from principle to implementation)

How to display text overflow? What are your needs...

Detailed explanation of Docker container network port configuration process

Exposing network ports In fact, there are two par...

Detailed explanation of MySQL phantom reads and how to eliminate them

Table of contents Transaction Isolation Level Wha...

Example of using Docker Swarm to build a distributed crawler cluster

During the crawler development process, you must ...

Detailed steps to install CentOS7 system on VMWare virtual machine

Pre-installation work: Make sure vmware workstati...

Detailed explanation of Linux commands and file search

1. Perform file name search which (search for ...

mysql 5.7.18 winx64 free installation configuration method

1. Download 2. Decompression 3. Add the path envi...

Nginx content cache and common parameter configuration details

Use scenarios: The project's pages need to lo...

Detailed explanation of using Vue custom tree control

This article shares with you how to use the Vue c...

What you need to know about creating MySQL indexes

Table of contents Preface: 1. Create index method...

Detailed explanation of Java calling ffmpeg to convert video format to flv

Detailed explanation of Java calling ffmpeg to co...