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

MySql Sql optimization tips sharing

One day I found that the execution speed of a SQL...

6 solutions to IDEA's inability to connect to the MySQL database

This article mainly introduces 6 solutions to the...

HTML&CSS&JS compatibility tree (IE, Firefox, Chrome)

What is a tree in web design? Simply put, clicking...

Detailed explanation of MySQL date addition and subtraction functions

1. addtime() Add the specified number of seconds ...

An example of using CSS methodologies to achieve modularity

1. What are CSS methodologies? CSS methodologies ...

How to install iso file in Linux system

How to install iso files under Linux system? Inst...

Analysis of MySQL Aborted connection warning log

Preface: Sometimes, the session connected to MySQ...

Vue implements image dragging and sorting

This article example shares the specific code of ...

A Deeper Look at SQL Injection

1. What is SQL injection? Sql injection is an att...

Usage and best practice guide for watch in Vue3

Table of contents Preface🌟 1. API Introduction 2....

Use docker to deploy tomcat and connect to skywalking

Table of contents 1. Overview 2. Use docker to de...

HTTPS Principles Explained

As the cost of building HTTPS websites decreases,...

MySQL database operations (create, select, delete)

MySQL Create Database After logging into the MySQ...

Detailed explanation of TypeScript 2.0 marked union types

Table of contents Constructing payment methods us...