整个动态路由的设置是我自己研究写的,现在项目中没发现什么问题。如发现有问题,欢迎前来纠正,谢谢!!!
链接:https://pan.baidu.com/s/1J9R2TkqJk0H9JMjqp2WcFw
提取码:n4rk
复制这段内容后打开百度网盘手机App,操作更方便哦
此包因为涉及后台交互未写成mock形式,下载后不可本地运行。node_modules需要自己本地安装。
可以参考项目中相关页面的设置
功能讲解如下:
cnpm install vue-router --save
注意参数--save
--save 可以理解成生产环境,会把依赖包名称添加到 package.json 文件 dependencies 键下,dependencies是运行时依赖。
--save-dev 则是开发环境, 添加到 package.json 文件 devDependencies 键下,devDependencies是开发时的依赖,如生产时不需要用到压缩库应该安装到devDependencies 。
动态路由
相关网址:例1 https://blog.csdn.net/s8460049/article/details/61190709
例2 http://www.jb51.net/article/123774.htm (脚本之家)
例3 https://segmentfault.com/a/1190000009506097 (根据权限设置路由)
具体实现
创建vue实例的时候将vue-router挂载,但这个时候vue-router挂载一些登录或者不用权限的公用的页面。
当用户登录后,获取用role,将role和路由表每个页面的需要的权限作比较,生成最终用户可访问的路由表。
调用router.addRoutes(store.getters.addRouters)添加用户可访问的路由。
使用vuex管理路由表,根据vuex中可访问的路由渲染侧边栏组件。
小建议:这里还有一个小hack的地方,就是router.addRoutes之后的next()可能会失效,因为可能next()的时候路由并没有完全add完成,好在查阅文档发现
next('/') or next({ path: '/' }): redirect to a different location. The current navigation will be aborted and a new one will be started.
根据权限生成动态路由步骤:
1.路由配置
main.js
router: router.js index.js
2.登录成功 因路由还是默认路由,页面跳转到404,解决方法如下:
login.js 动态添加路由
3.页面刷新 页面跳转到404,解决方法如下:
这是因为刷新会导致Vue重新实例化,路由也恢复到了初始路由,于是当前路径又被重定向到了404,
这个问题的根源是可用路由没有实现持久化,
那么可以通过将路由数据存sessionStorage来解决,实例化之前如果检测到本地路由就直接合并路由
解决办法:初始路由删除404配置,动态添加
router.js
main.js
4.菜单栏始终未空 未能加载路由
1.addroute已经成功了,所以可以跳转到新增的路由页。
2. addroute只是在路由里加了新的路由,也就是你可以通过url跳转,并不是个你添加新的菜单,加新的菜单还需要你自己根据权限判断,写代码处理
3.渲染menu不应该遍历路由去生成,因为addroutes后,路由虽然增加了,但路由不是响应数据(未观察,且未订阅),是不会对你的视图触发变化的。
①解决办法:指令 Vue.directive
②建议解决方案:使用vuex,对路由信息进行状态管理,把初始的路由数据存到store里,menu依靠store进行渲染及更新,addroutes后再把新增路由push进store存储的路由数组中,即可以触发menu更新。
----------------------------------------------------------------------------------------------------------------------
实际步骤:
①store module : permission.js
action:GenerateRoutes 根据角色生成动态路由
import { constRouters, appRouterAdmain, appRouterManger, appRouterYyb } from '../../routes/routes'
/**
* 通过meta.role判断是否与当前用户权限匹配
* @param roles
* @param route
*/
function hasPermission(roles, route) {
if (route.meta && route.meta.roles) {
return roles.some(role => route.meta.roles.indexOf(role) >= 0)
} else {
return true
}
}
/**
* 递归过滤异步路由表,返回符合用户角色权限的路由表
* @param asyncRouterMap
* @param roles
*/
function filterAsyncRouter(asyncRouterMap, roles) {
const accessedRouters = asyncRouterMap.filter(route => {
if (hasPermission(roles, route)) {
if (route.children && route.children.length) {
route.children = filterAsyncRouter(route.children, roles)
}
return true
}
return false
})
return accessedRouters
}
const permission = {
state: {
routers: constRouters,
addRouters: []
},
mutations: {
SET_ROUTERS: (state, routers) => {
state.addRouters = routers
state.routers = constRouters.concat(routers)
}
},
actions: {
GenerateRoutes({ commit }, data) {
return new Promise(resolve => {
const { roles } = data
let accessedRouters
console.log(data)
if (roles.indexOf('admin') >= 0) {
accessedRouters = appRouterAdmain
}else if (roles.indexOf('shenhe') >= 0) {
accessedRouters = appRouterManger
}else if (roles.indexOf('999') >= 0) {
accessedRouters = appRouterYyb
}
commit('SET_ROUTERS', accessedRouters);
resolve()
})
}
}
}
export default permission
②getter 方法
③home.vue 导入store 数据
5.router.beforEach 无限循环,页面跳转不会触发无限循环,刷新页面就会
原因:
调用next()时会直接进入to路由,不会再调用beforeEach()
而调用next('xxx')后会拦截路由使得路由重定向xxx,并再次调用beforeEach(),因此必须做好条件判断避免陷入死循环。
解决步骤:
①将所有next('xxx') --> next() 问题还是没解决。
②发现是重复添加路由造成。
Home.vue 已经调用了路由添加功能,与 router.beforeEach 添加路由重复冲突
5.静态路由正常。动态路由刷新页面不能展开当前路由 点击跳转没问题
猜想:
①可能是因为路由是动态加载,动态路由在for循环之后,所以未能展开
②可能是vue 参数传的不对
解决办法:
① 固定展示某一项 :default-openeds="['1']"
问题: 但是每次点击切换其他路由,路由刷新 固定指向第一个路由。
②需动态展示当前栏目
第一次进入页面/刷新页面 点击切换页面正常显示
相关动态路由设置代码:
6.换一种路由添加方式
home.vue 去掉动态更改路由方法
menuItem: function() {
// 动态获取可访问路由表
// this.$router.options.routes = this.$store.state.permission.addRouters;
// return this.$store.state.permission.addRouters
}
效果:
首次登录: 刷新页面:
路由由vuex获取:$router.options.routes ===> $store.getters.addRouters
import store from "../vuex/store"
main.js 设置路由
new Vue({
router,
store,
render: h => h(App),
created: function() {
let isLogin = util.getCookie('role');
if(!isLogin){
return this.$router.push({path:'/login'});
}
//存菜单
let userPath = '';
if(isLogin == 20){
userPath = constRouters.concat(appRouterManger);
}else if(isLogin == 50){
userPath = constRouters.concat(appRouterYyb);
}else{
userPath = constRouters.concat(appRouterAdmain);
}
//注入时拼接404处理路由
this.$router.addRoutes(userPath.concat([{
path: '*',
redirect: '/404'
}]));
// 因为addroutes后,$router.options.routes不会更新,所以需要手动添加。
// 最后发现这句话可以不加
this.$router.options.routes = userPath;
},
mounted () {
}
}).$mount('#app')
main.js --> router.beforeEach 用户权限路由有store分配
new Vue({
.....
//存菜单
let userPath = '';
if(isLogin == 20){
userPath = constRouters.concat(appRouterManger);
}else if(isLogin == 50){
userPath = constRouters.concat(appRouterYyb);
}else{
userPath = constRouters.concat(appRouterAdmain);
}
//注入时拼接404处理路由
this.$router.addRoutes(userPath.concat([{
path: '*',
redirect: '/404'
}]));
})
上面的存菜单代码块替换为:
let userPath = constRouters.concat(store.getters.addRouters);
//注入时拼接404处理路由
this.$router.addRoutes(userPath.concat([{
path: '*',
redirect: '/404'
}]));
vuex - moudle - permission.js 设置权限路由:
登陆成功后页面为空:
解决办法:
login.vue 登录接口内部手动添加路由 : this.$router.addRouters()
至此动态路由功能完成,没问题!