最近做项目,遇到了动态路由权限问题,看了一些文章,踩了两天坑,算是实现了。和大家分享一下,有错误的地方请大神指出来。目前没有接口,我采用的vuex存储用户名信息来获取配置的路由js。
1、先看一下我的路由目录,如下:
1.1、_import_development.js;这个是开发环境引入组件的方式,代码如下:
这里的路径按照自己的代码存放获取。(我的组件存放是按照路由分的文件夹,自我感觉非常清晰)
module.exports = file => require('@/pages/components/' + file + '/index.vue').default;
1.2、_import_production.js;这个是生产环境引入组件的方式,代码如下:
module.exports = file => () => import ('@/pages/components/' + file + '/index.vue');
1.2、index.js;这个是路由主js,代码如下:
import Vue from 'vue'
import Router from 'vue-router'
import staticRouter from './staticRouter'//静态路由
Vue.use(Router)
const originalPush = Router.prototype.push;
Router.prototype.push = function push(location) {
return originalPush.call(this, location).catch(err => err)
};
const router = new Router({
routes: staticRouter
});
export default router;
1.4、resetRouter.js;这个重置路由,用于切换用户后重置路由,代码如下:使用方法:在系统任意界面直接引入此js,在销毁周期调用此函数,可重置路由;
import Vue from 'vue'
import Router from 'vue-router'
import router from '@/router'
import staticRouter from './staticRouter'//静态路由
export function resetRouter() {
const newRouter = new Router({
routes: staticRouter
});
router.matcher = newRouter.matcher;
}
// 重置路由
import {
resetRouter
} from '@/router/resetRouter.js';
//销毁阶段直接使用
destroyed() {
resetRouter(); //退出系统,重置路由
}
1.5、staticRouter.js;静态路由存放(这里不能引入404路由,否则点击完跳转直接进入404,404配置我在动态js里配置)
import login from '@/components/login'; //系统架构单独引入
import serverError from '@/components/serverError'; //服务器错误
const staticRouter = [{
"path": "/",
"name": "login",
"component": login
},
{
"path": "/serverError",
"name": "serverError",
"component": serverError
}
];
export default staticRouter;
第一阶段完毕,我的路由配置文件夹是这样的,接下来我们讲解如何引用这些文件。
2、路由需要在两个js中引入:
2.1、main.js引入,这个我就不讲了。大家都会。
2.2 、动态路由js,这里我会细讲一下如何使用,我的命名:getRouter.js,写在配置文件夹下边,如下:
2.2.1、引入文件
import router from '@/router';//路由
import axios from 'axios';//axios请求,
import store from '@/store';//vuex
import NProgress from 'nprogress';//页面加载进度条
//获取组件的方法,一种开发环境,一种生产环境
const _import = require('@/router/_import_' + process.env.NODE_ENV);
import system from '@/pages'; //系统架构单独引入
import pageError from '@/components/pageError'; //路由错误 404
let systemRouter; //系统菜单,这里要提前声明,否则直接添加没有判断,会进入死循环
2.2.2、获取路由,在路由前置守卫获取
router.beforeEach(async(to, from, next) => {
// 判断路由是否去登录界面
NProgress.start();//路由动画,自己直接装npm 就可以
if (to.name === 'login') {//如果进入登录页面,我们直接进行路由连接
systemRouter = undefined;//先清空系统路由变量
next();
} else {
// 判断是否已经登录
const islogin = JSON.parse(window.sessionStorage.getItem("isLogin"));
if (islogin) {
// 获取登录信息,储存在vuex
const userDeatilInfo = JSON.parse(window.localStorage.getItem("userDeatilInfo"));
store.dispatch('userInfo/setUserInfo', userDeatilInfo);
//判断是否有系统路由
judgeHasSystem(to, next)
} else {
// 未登录跳转至登陆页
next({
path: './'
});
}
};
});
//路由后置钩子,路由结束动画
router.afterEach(() => {
NProgress.done()
});
// 判断是否有系统页码
function judgeHasSystem(to, next) {
// 如果有则直接跳转,这里就需要用到声明的系统路由
if (systemRouter) {
next();
} else {
// 直接进行请求获取新的菜单
// 404界面在动态路由配置,否则无法进行登录导航
let systemRouterStr = [{
"path": "*",
"name": "pageError",
"component": 'pageError'
}];
// 如果本地没有系统路由缓存则进行异步获取
//我这里使用的是本地配置文件,如果真是后台,下边部分大家可以修改成axios方式,可以用
// async await;或者直接在.then之后进行操作,
const username = store.state.userInfo.useInfo.username;
if (configRouter[username]) {
systemRouterStr.push(configRouter[username][0])
} else {
systemRouterStr.push(configRouter.other[0])
};
systemRouter = systemRouterStr;
routerNext(to, next);//执行跳转
}
}
// 执行跳转
function routerNext(to, next) {
const realRouter = filterAxiosRouter(systemRouter) //过滤路由
router.addRoutes(realRouter) //动态添加路由
// 执行跳转
next({
...to,
replace: true
});
};
// 加载组件过滤路由
function filterAxiosRouter(asyncRouterMap) { //遍历后台传来的路由字符串,转换为组件对象
const accessedRouters = asyncRouterMap.filter(route => {
if (typeof(route.component) === 'string') {
if (route.component) {
switch (route.component) {
case 'system':
route.component = system;
break;
case 'pageError':
route.component = pageError;
break;
default:
// router里已经声明了获取组件的方式,回顾两种环境下的引入组件方式
route.component = _import(route.component);
break;
};
};
}
//判断是否有子路由
if (route.children && route.children.length) {
route.children = filterAxiosRouter(route.children);
};
return true
});
return accessedRouters
};
2.2.3、将获取路由的js,在main.js种引入
import '@/utils/getRouter.js'; //获取路由
个人配置的路由静态文件,仅供参考
const configRouter = {
//管理员路由
admin: [{
"path": "/system",
"name": "system",
"component": "system",
"children": [{
"path": "",
"name": "1",
"component": "1",
"meta": {
"title": "1"
}
}, {
"path": "2",
"name": "2",
"component": "2",
"meta": {
"title": "2"
}
}, {
"path": "3",
"name": "4",
"component": "4",
"meta": {
"title": "3"
}
}, {
"path": "4",
"name": "4",
"component": "4",
"meta": {
"title": "4"
}
}, {
"path": "5",
"name": "5",
"component": "5",
"meta": {
"title": "5"
}
}]
}],
// 其他路由
other: [{
"path": "/system",
"name": "system",
"component": "system",
"children": [{
"path": "",
"name": "2",
"component": "2",
"meta": {
"title": "2"
}
}, {
"path": "3",
"name": "3",
"component": "3",
"meta": {
"title": "3"
}
}]
}, ]
}
至此,我的动态路由是这样配置的,如果有缺陷,请大神指导指导,谢谢。