• vue路由动态添加


    需求:根据登录的角色不一样,实现不同的路由展示,例如:超级管理员登录能访问所有菜单,普通用户登录就只能展示部分菜单。

    1.首先在路由里面配置两份路由,一份静态的默认路由,例如登录页面,404页面

    export const constantRoutes = [
        {
            path: '/',
            redirect:'/login'
        },
        {
            path: '/login',
            component: () => import('@/view/login')
        }, {
            path: '/404',
            component: () => import('@/view/404')
        }, {
            path: '/main',
            name:'main',
            component: () => import('@/view/main'),
            children: [{
                path: 'home',
                component: () => import('@/view/asyncPage/home')
            }]
        }
    ]

    然后在配置一份动态的路由,每个路由添加上roles属性,表明该路由那些角色能够访问

    export const asyncRoutes = [{
        path: 'xtgl',
        id:"2",
        icon:"el-icon-s-tools",
        toPath:'/main/xtgl',
        component: () => import('@/view/asyncPage/系统管理'),
        meta: {
            title: '系统管理',
            roles: ['admin', 'vip']
        },
        children: [{
            path: 'jsgl',
            id:"2-1",
            toPath:'/main/xtgl/jsgl',
            component: () => import('@/view/asyncPage/角色管理'),
            meta: {
                title: '角色管理',
                roles: ['admin', 'vip']
            },
        }, {
            path: 'zhgl',
            id:"2-2",
            toPath:'/main/xtgl/zhgl',
            component: () => import('@/view/asyncPage/账号管理'),
            meta: {
                title: '账号管理',
                roles: ['admin']
            },
        }]
    }, {
        path: 'ddgl',
        id:"3",
        toPath:'/main/ddgl',
        component: () => import('@/view/asyncPage/订单管理'),
        meta: {
            title: '订单管理',
            roles: ['admin', 'vip']
        },
        children: [{
                path: 'ddfh',
                id:"3-2",
                toPath:'/main/ddgl/ddfh',
                component: () => import('@/view/asyncPage/订单发货'),
                meta: {
                    title: '订单发货',
                    roles: ['admin', 'vip']
                },
            },
            {
                path: 'ddlb',
                id:"3-1",
                toPath:'/main/ddgl/ddlb',
                component: () => import('@/view/asyncPage/订单列表'),
                meta: {
                    title: '订单列表',
                    roles: ['admin']
                },
            }, {
                path: 'wddd',
                id:"3-3",
                toPath:'/main/ddgl/wddd',
                component: () => import('@/view/asyncPage/我的订单'),
                meta: {
                    title: '我的订单',
                    roles: ['admin','vip']
                },
                children: [{
                        path: 'qbdd',
                        id:"3-3-1",
                        toPath:'/main/ddgl/wddd/qbdd',
                        component: () => import('@/view/asyncPage/全部订单'),
                        meta: {
                            title: '全部订单',
                            roles: ['admin']
                        },
                    },
                    {
                        path: 'wcdd',
                        id:"3-3-2",
                        toPath:'/main/ddgl/wddd/wcdd',
                        component: () => import('@/view/asyncPage/完成订单'),
                        meta: {
                            title: '完成订单',
                            roles: ['admin', 'vip']
                        },
                    }
                ]
            },
        ]
    }, {
        path: 'xxgl',
        id:"4",
        toPath:'/main/xxgl',
        redirect:'/main/xxgl/thgl',
        // component: (resolve) => require(['@/view/asyncPage/学校管理'], resolve),//映射的组件
        component: () => import('@/view/asyncPage/学校管理'),
        meta: {
            title: '学校管理',
            roles: ['admin', 'vip']
        },
        children: [{
                path: 'thgl',
                id:"4-1",
                toPath:'/main/xxgl/thgl',
                component: () => import('@/view/asyncPage/教师管理'),
                meta: {
                    title: '教师管理',
                    roles: ['admin', 'vip']
                },
            },
            {
                path: 'xsgl',
                id:"4-2",
                toPath:'/main/xxgl/xsgl',
                component: () => import('@/view/asyncPage/学生管理'),
                meta: {
                    title: '学生管理',
                    roles: ['admin']
                },
            }, {
                path: 'jzgl',
                id:"4-3",
                toPath:'/main/xxgl/jzgl',
                component: () => import('@/view/asyncPage/家长管理'),
                meta: {
                    title: '家长管理',
                    roles: ['admin']
                },
            }
        ]
    },{
        path: 'sz',
        id:"5",
        toPath:'/main/sz',
        component: () => import('@/view/asyncPage/设置'),
        meta: {
            title: '设置',
            roles: ['admin', 'vip','user']
        }
    }]

    2.然后封装一个函数,用来从动态路由中过滤当前角色能够访问的路由

    function hasPermission(roles, route) { //判断角色是否有该路由的权限
        if (route.meta && route.meta.roles) {
            return route.meta.roles.includes(roles)
        } else {
            return true
        }
    }
    
    function filterAsyncRoutes(asyncRoutes, roles) {
        let r = [];
        asyncRoutes.map((item) => {
            const tmp = { ...item
            };
            if (hasPermission(roles, tmp) && !tmp.children) {
                r.push(tmp)
            } else if (hasPermission(roles, tmp) && tmp.children) {
                r.push({
                    path: tmp.path,
                    id: tmp.id,
                    component: tmp.component,
                    meta: tmp.meta,
                    toPath:tmp.toPath,
                    children: filterAsyncRoutes(tmp.children, roles)
                })
            }
        })
        // 返回角色拥有的权限路由
        return r;
    }
    export default filterAsyncRoutes;

    3.登录的时候更具后台返回的角色(我这里使用mock 模拟后台返回的数据,只定义了3种角色,admin vip 和user),调用刚封装的函数,获取到该角色拥有权限的路由,调用addRoute动态注册该路由,并把路由存到

    sessionStorage里面方面后面使用组件渲染。
    login(){
        // 登录前预校验
        this.$refs.loginFromRef.validate(res=>{
            if(res){
                this.axios.post('/login',this.loginFrom).then(res=>{
                    let {data:{data}} = res;
                    let userInfo = data.userInfo;
                    window.sessionStorage.setItem('token',userInfo.token);
                    window.sessionStorage.setItem('identity',userInfo.identity);
                    this.$store.commit('loginIn',userInfo)
                    let ro = JSON.stringify(filterAsyncRoutes(asyncRoutes, userInfo.identity))
                    console.log("登录重新注册路由",ro);
                    window.sessionStorage.setItem('router', ro);
                    resetRouter()
                    filterAsyncRoutes(asyncRoutes, userInfo.identity).forEach(item => {
                        router.addRoute('main', item)
                    })
                    //路由添加完成后在动态添加404 ,解决刷新后页面跳404 和路由找不到的时候跳404
                    router.addRoute({
                        path: '*',
                        redirect: '/404'
                    })
                    this.$router.push('main/home');
                }).catch(err=>{
                    console.log(err);
                })
            }else{
                return;
            }
        })
    },

    4,登录后如果刷新页面,路由会失效,所有在路由守卫里面在添加一次动态路由注册,解决该问题

    let oneRun = true; //防止路由死循环
    router.beforeEach((to, from, next) => {
        let roles = window.sessionStorage.getItem('identity');
        if (to.path == '/login') {
            return next()
        } else {
            let token = window.sessionStorage.getItem('token');
            token ? next() : next('/login')
        }
        // 每次跳转前存入要跳转的路径当成当前选中项的id
        window.sessionStorage.setItem('currIndex',to.path);
        if(_this){
             _this.$store.commit('setCurrIndex',to.path);
             console.log( _this.$store.state.currIndex);
        }
        if(oneRun){
            oneRun=false;
            console.log(asyncRoutes,roles);
            window.sessionStorage.setItem('router', JSON.stringify(filterAsyncRoutes(asyncRoutes, roles)));
            console.log("路由守卫重新注册路由");
            filterAsyncRoutes(asyncRoutes, roles).forEach(item => {
                router.addRoute('main', item)
            })
            //路由添加完成后在动态添加404 ,解决刷新后页面跳404 和路由找不到的时候跳404
            router.addRoute({
                path: '*',
                redirect: '/404'
            })
            next({...to,replace:true})
        }
    })

    大体的思路就是这样的,源码传到了码云上,给大佬奉上仓库地址:https://gitee.com/wbw1993/vue-dynamic-routing

    效果图:登录的用户名是admin能访问所有的菜单,vip只能展示部分菜单,其他用户名都只能看到首页和设置两个菜单

     

     结语:代码未经优化,欢迎各位大佬指出不足的地方

    路漫漫其修远兮...

  • 相关阅读:
    web component的理解
    cdn
    const 命令
    let 的含义,及let 与 var 的区别
    选择器
    Qt5:Qt中一些函数功能介绍
    给软件工程师自学的建议
    Qt5:渐变效果的实现
    Wayland软件库 :替代 X Window 的软件库
    Qt5:窗口各类位置
  • 原文地址:https://www.cnblogs.com/wubaiwan/p/16176749.html
Copyright © 2020-2023  润新知