ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

vue路由动态添加

2022-04-21 22:34:34  阅读:180  来源: 互联网

标签:vue roles component 添加 meta path main 路由


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

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只能展示部分菜单,其他用户名都只能看到首页和设置两个菜单

 

 

 

 

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

路漫漫其修远兮...

 

标签:vue,roles,component,添加,meta,path,main,路由
来源: https://www.cnblogs.com/wubaiwan/p/16176749.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有