动态路由权限

路由权限的实现,基本原理是添加一个全局的前置钩子函数router.beforeEach(hook),这个函数会在路由切
换开始时调用,即在用户登录时,获取用户权限表,通过权限表与白名单对比,利用addRoutes()方法动
态挂在路由,即实现权限控制。下面我将对至二级路由的权限控制的思路即重要代码分布介绍:

我大体介绍一下本人项目中需要用到控制的点:平台中有三种登录身份:主账号,子账号,运营者账号;对子账号和运营者账号
分别显示不同功能页面。项目开发之初,利用v-show写的死页面,后期为了实现主账号可动态控制子账号与运营者账号权限页
面,故而利用钩子函数实现控制。不同身份的路由权限表可以是以下格式:

  // 子账号:[
  //   {name:'首页',path:'/index'},
  //   {name:'首页-异常设备',path:'/index/home2'},
  // ]
  // 运营者账户:[
  //   {name:'首页',path:'/index'},
  //   {name:'首页-收益看板',path:'/index/home1'},
  //   {name:'首页-异常设备',path:'/index/home2'},
  // ]

具体格式可在学习完之后,自己定义;

第一步:设置router–index.js设置白名单(即不分权限都要显示的组件路由)和所有需要区别挂载的路由

大体格式如下:
1》引入

import Vue from 'vue'
import Router from 'vue-router'

const inner = () =>
    import ('@/components/inner.vue');
const user = () =>
import ('@/components/user.vue'); //登录注册
const loginandregister = ()=>
    import ('@/user/loginandregister.vue'); //登录注册   const forgetkey = () =>
    import ('@/user/forgetkey.vue'); //忘记密码
    const index = () =>
        import ('@/views/index.vue'); //首页
    const home1 = () =>
        import ('@/index/home1.vue'); //首页--收益看板
    const home2 = () =>
        import ('@/index/home2.vue'); //首页--设备异常
    
Vue.use(Router)

2》设置白名单

export  const constantRouterMap = [
    //用户中心========
    {
        path: '/user',
        alias: '/',
        name: 'user',
        component: user,
        children: [{ //登录注册
                path: 'loginandregister',
                alias: '/',
                name: 'loginandregister',
                component: loginandregister,
            },           
            {//忘记密码=======
                path: 'forgetkey',
                alias: '/',
                name: 'forgetkey',
                component: forgetkey,
            },
    {
        path: '/jump',
        name: 'jump',
        component: jump,
        alias: '/',
    },
    {
        path: '/inner',
        name: 'inner',
        component: inner,
    },
]

3》动态需要根据权限加载的路由表

export const asyncRouterMap = [{
        name: "inner",
        path: "/inner",
        component: inner,
        children: [ // 首页=========================
            {
                path: '/index',
                name: '/index',
                cname: '首页',
                component: index,
                children: [],
                mate: true,
            },
            {
                path: '/home1',
                name: '/index/home1',
                component: home1,
                cname: '收益看板',
            },
            {
                path: '/home2',
                name: '/index/home2',
                component: home2,
                cname: '设备异常',
            },
        ]
    }

4》实例化vue的时候只挂载constantRouter

export default new Router({
    mode: 'history',
    routes: constantRouterMap
});

第二步:获取权限表

用户登录时获取权限表,并存于localStorage中(roleinfo)

第三步:在mian.js中添加钩子函数

1》首先引入vuex和路由文件index.js

import Vuex from "vuex"
import store from "./vuex/store"
import { constantRouterMap, asyncRouterMap } from '@/router'

2》编写钩子函数逻辑

router.beforeEach((to, from, next) => {
    let token =***; //获取登陆时的token,
    let userid = ***;//获取登陆时用户的id,
    let localrole = localStorage.getItem('role'); //
    let localroleinfo = JSON.parse(localStorage.getItem('roleinfo')); //获取本地路由权限信息
    if (!token || !localrole || !localroleinfo || !userid) { //以上四种缺少一样则退回登陆页面,此步骤确保本地存储里是有路由权限表的
        if (to.path == '/loginandregister') { //若是主动跳至登录页,则执行
            next();
        } else { //若是跳到其它页面,则返回登录页面
            next('/loginandregister')
        }
    }
    //,此处我在vuex中储存权限表的变量是getRoles , getRolesinfo
    if (!store.getters.getRoles || from.path == '/loginandregister') { //如果VUEX里没有路由权限信息,或者是由登录页面跳转而来
        store.dispatch('setRoles', localrole).then(() => { //dispatch():查找store所有父级,直到找到要找的父组件,并触发指定事件,(此处触发保存信息至VUEX事件,set...)查找setroles,并将localrole的值赋给它
            store.dispatch('setRolesinfo', localroleinfo).then(() => {}) //给setrolesinfo赋值localroleinfo
        })
        const inner = () =>
            import ('@/components/inner.vue');
        let ctouter = [ //此处拉出需要权限判断的全部子路由的公共父级,即index.js中的asyncRouterMap
            {
                name: "inner",
                path: "/inner",
                component: inner,
                children: []
            }
        ]
        let newa = asyncRouterMap[0].children;
        console.log('first', newa)
        let newarr = [];
        for (let i = 0; i < newa.length; i++) { //循环需要权限的总路由表
            for (let y in localroleinfo) { //循环获得的权限路由表
                if (newa[i].name == localroleinfo[y]) {//这一步是从后台获取的路由表与asyncRouterMap比对
                    newarr.push(newa[i]) //先得出完整的权限路由,但此时未区分父级子集
                }
            }
        }

//以下步骤用来区分父级子集,具体逻辑可自行设计

let firstarr = [];
for (let v = 0; v < newarr.length; v++) { //得到一级路由
    if (newarr[v].mate) {
        firstarr.push(newarr[v]);
        newarr.splice(v, 1, '00')
    }
}
for (let q = 0; q < newarr.length; q++) {
    for (let w = 0; w < firstarr.length; w++) {
        let qwe = new RegExp(firstarr[w].path);
        if (qwe.test(newarr[q].name)) {
            firstarr[w].children.push(newarr[q]);
            newarr.splice(q, 1, '00')
        }
    }
}
ctouter[0].children = firstarr;
store.dispatch('setSrouter', ctouter).then(() => {
    router.addRoutes(ctouter) //vue api ---- addRouter ---- 动态挂载路由,即可以进入的路由
})
}
next()
});

(个人整理使用的感觉比较简单的权限控制方法,直接比对,如果有错误,欢迎指出)

猜你喜欢

转载自blog.csdn.net/qq_42896240/article/details/87629769