Permission Control Mode

Routes are returned entirely from the back end

Validation control logic

Agree on the backend return data format

{children: [] component: {children: [] component:"views/index/content/index"
        id: 5
        meta: {isLogin: 1, icon: "el-icon-postcard", title: "Xx navigation submenu", isShow: 1}
        name: "/home/index/content"
        path: "/home/index/content"
    }
]
component: "views/index"// File address of the corresponding page ID: 3 // Unique attribute // isLogin Check whether login is required to access, isShow check whether it is displayed on the navigation bar, title Display navigation bar name meta: {isLogin: 1, icon:"el-icon-date", title: "Xx navigation", isShow: 1} 
name: "index"// Component name path:"index"// Routing addressCopy the code

Vue configuration

1. The APP. Vue configuration

<template>
  <div id="app">
    <router-view />
  </div>
</template>

Copy the code

2. Set the homepage

According to the configuration of parent and child routes, child routes can be switched only when rout-view is available. Therefore, you need to set the navigation bar on the home page and the page corresponding to the navigation bar route

Something like this layout

<template>
    <div class="main">
        <div class="main-left"> <! </div> <div class="main-right"> <! --> <div class="main-right-container">
                <router-view></router-view>
            </div> 
        </div>   
    </div>    
</template>

Copy the code

Login page Settings

Introduce vuEX data

computed: { ... mapGetters(['menuList']) }, methods: { ... mapActions(['getMenuList',]).}Copy the code
// Function triggered after loginlogin() {
     let url='/ your API address ';
     let reqData={};
    
     let res = await this.$Http.axiosPost(url, reqData); // Use axios here. Later there will be an article on axios configuration to the prototype chainifRes.code === 200) {// Save login statuslocalStorage.setItem('Flag'.'isLogin'); // Save the login tokenlocalStorage.setItem('TOKEN',res.obj); // Call mapGetters to check whether vuEX has routing datalet code = await this.getMenuList();
        if(code === 200){// Route exists // Jump to navigation pagelet Path= this.menuList[0].children[0].children[0].path
          
          this.$router.push({path: Path})
        }else{// No route exists, indicating configuration problem console.log('Route fetch failed', code)
          MessageBox({
            title: 'warning',
            message: 'Navigation configuration problem, please contact administrator', callback: action => {// callback functionlocalStorage.clear(); // Clear cached data next({path:'/login', replace: true}) // Jump to login}})}}Copy the code

Configuration vuex

import Vue from 'vue'
import Vuex from 'vuex'
import { normalRouter } from '.. /router'
import createLogger from 'vuex/dist/logger'Use (Vuex) // Set the log to be printed only in the development environment const debug = process.env.node_env! = ='production'

const state = {
    menuList: []
}
const getters = {
    menuList: state => state.menuList
}
const mutations = {
   setMenuList (state, value) {// Save data state. MenuList = menus; Menus. concat(normalRouter) // Matcher is used to resolve a Duplicate named routes definition error VueRouter. Matcher = new Router().matcher // The error page should be added last, otherwise the first to visit the dynamic route 404 menus.push({path:The '*'// redirect to 404 page if the page does not exist:'/error'}) VueRouter. AddRoutes (Menus)}} const actions = {// get dynamic route async getMenuList({commit}) {// get route data through the interfacelet url='/ your API address ';
    let reqData={};
    
    let res = await this.$Http.axiosPost(url, reqData); // Use axios here. Later there will be an article on axios configuration to the prototype chainif(res. Code = = = 200) {/ / / / res success. Obj [0]. The component ="views/homepage"
      letMenus = needRoutes(res.obj) // Generate routing information // 1. // A file containing a homepage folder // 2. The obtained routes are all subroutes under /home, so after obtaining the routing data, it is put into children to commit('setMenuList',  [{
        path: "/home",
        component:(resolve) =>{
          require(['@/views/homepage'],resolve)
        },
        meta: { isLogin: true}, children:menus}])return res.code
    } else{/ / failurereturnRes.code}}} // Generate routing dataletNeedRoutes = (data) => {// Check if it is an arrayif(! Array.isArray(data)) {return new TypeError('arr must be an array.');
  }
  let arr = formatComponent(data)
  
  returnarr; } // A recursive function for asynchronous rendering of components and routeslet formatComponent = (data) => {
  for (letObj of data) {const component = obj.component.resolve => {require([)'@ /' + component], resolve) }
    if(obj.children. Length > 0) {// Children formatComponent(obj.children)}}return data
}

const store = new Vuex.Store({
    state,
    getters,
    mutations,
    actions,
    strict: debug,
    plugins: debug ? [createLogger()] : []
})
export default store
Copy the code

Build the navigation guard on the Router page

1. Confirm the default route

Level-1 route configuration and redirection // The login page and error page do not need to be determined by login and can be placed in the default routeexport const normalRouter = [
  {
    path: "/",
    redirect: '/login',
    // meta: {
    //   isLogin: false// add this field to indicate that the route needs to be logged in // title:'login'
    // }
  },
  {
    path: "/login",
    name: "Login",
    // components:require('./views/login'),
    component: resolve => require (['@/views/login'], resolve),
    meta: {
      isLogin: false// Add this field to indicate that the route is required to login the title:'login'
    }
  },
  {
    path: "/home",
    redirect: '/home/index',
  },
  {
    path: "/error",
    name: "error",
    component: error,
    meta: {
      isLogin: false// Add this field to indicate that the route is required to login the title:'wrong'}},]Copy the code

2. Import a route

let router = new Router({
  mode: "history",
  base: process.env.BASE_URL,
  routes:normalRouter
});
Copy the code

3. Configure the global route navigation guard

// Because we use ElementUI, we need to import ElementUI from'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)

router.beforeEach( async (to, from, next) => {
  console.log('before routing', to); // Get the cached login statuslet hasLogin = localStorage.getItem("Flag") // There is login statusif (hasLogin) {
    console.log('state'Store), the state, menuList. Length, the to and from) / / whether the vuex have deposited in the routing dataif(store. State. MenuList. Length = = = 0) {/ / to this step the user has logged on, and refresh the browser, however, lead to route to empty, so in vuex to request routinglet res = await store.dispatch('getMenuList') // If the code value is not 200, an error occurs on the routing interface and you need to log in againif(res ! // Element MessageBox({title:'warning',
          message: 'Navigation configuration problem, please contact administrator', callback: action => {// callback function // clear login cache datalocalStorage.clear(); // next({path:'/login', replace: true})}})}elseRouter. AddRoutes is asynchronous, so global jump * is added dynamically, using next({... to, replace:true}) reload next({... to, replace:true}}})if (to.name === 'Login'Next ({path: recursiveRouter(store.state.menulist [0]),})} {path: recursiveRouter(store.state.menulist [0]),})}else { // 正常跳转
      next()
    }
  } else{// If there is no login, the login page console.log('to', to) // Not logged in to want to access another page, jump toif(to.name ! = ='Login') {
      next({
        path: '/login'})},else{// If no route is matched, the first page of the route is displayed through recursive functionsif (to.name === 'error') {
       let path = recursiveRouter(store.state.menuList[0])
        next({
          path: path
        })
      } else{next()}}}}) // Recursive route, confirming the first route addresslet recursiveRouter = (data) => {
  if (data.children && data.children.length > 0) {
    return recursiveRouter(data.children[0])
  } else {
    return data.path
  }
}
Copy the code

conclusion

For the time being, this is a general permission control that can cover most business scenarios. The specific route redirect needs to be modified according to your own business scenarios. Any questions or suggestions can be written in the comments section

The resources

Summary of vUE permission routing implementation

About addRoutes and AXIos dynamically adding routes

How to gracefully add permission control to VUE