addRoutes:动态添加/注册路由,一般多用于后台返回菜单树的管理系统。
解决管理系统权限时一般可采用路由守卫按权限限制是否允许访问某些路由,但当权限分类众多、或者是时而有某些路由时而又没有时,用路由守卫可能将写众多判断,更不利于后期维护,这时候的路由守卫看起来不再是那么合适了。
用addRoutes会有不一样的结果吗?动态添加路由将会从根源上切死访问权限,而不是去判断。设想一下,假如一个路由都不存在,那你去访问它,还需要去做大量判断他是否有权限吗?
当然如果不是后台返回菜单树,那两种解决方案可能看起来差别并不是很大,因需要前端去判断是否去注册该路由,这种方式与添加路由守卫去判断时候允许访问该路由的代码逻辑量区别不大
总体来说如果是后台返回菜单树,建议使用addRoutes,如果不返回菜单树则根据权限是否简单明了去区分,如果简单明了则使用路由守卫,否则建议采用addRoutes(路由守卫也并不是不行)
addRoutes用法实例(下例是在app.vue中使用,具体看实际需求):
import { mapActions } from 'vuex'
export default {
name: 'App',
data(){
return{
}
},
created(){
//使用定时器模拟请求后台获取菜单树
setTimeout(()=>{
//获取菜单树success,假设返回实例如下
var menuTree = [
{
name:'首页',//路由名称
disabled:false,//是否具有访问权限,true代表被禁用
},
{
name:'订单',
disabled:false,
children:[
{
name:'历史订单',
disabled:true,
},
{
name:'进行中订单',
disabled:false,
},
{
name:'订单详情',
disabled:false,
},
]
},
{
name:'我的',
disabled:true,
children:[
{
name:'我的钱包',
disabled:true,
},
{
name:'我的信息',
disabled:true,
},
]
},
];
//根据返回菜单树与前端拟定菜单树逻辑处理(匹配vue组件),获取出实际菜单树
//前端拟定菜单树假设如下
var draftTree = [
{
name:'首页',//路由名称
path:'index',//路由
component:()=>import("@/pages/index")//对应的vue组件
},
{
name:'订单',
path:'order',
component:()=>import("@/pages/order"),
children:[
{
name:'历史订单',
path:'orderHistory',
component:()=>import("@/pages/order/history"),
},
{
name:'进行中订单',
path:'orderNew',
component:()=>import("@/pages/order/new"),
},
{
name:'订单详情',
path:'orderDetails',
component:()=>import("@/pages/order/details"),
},
]
},
{
name:'我的',
path:'a',
component:()=>import("@/pages/a"),
children:[
{
name:'我的钱包',
path:'ab',
component:()=>import("@/pages/a/ab"),
},
{
name:'我的信息',
path:'ac',
component:()=>import("@/pages/a/ac"),
},
]
},
];
//逻辑处理此处省略(遍历menuTree,匹配插入所需字段),处理结果如下
var menuArr = [
{
name:'首页',//路由名称
disabled:false,//是否具有访问权限,true代表被禁用
path:'index',//路由
component:()=>import("@/pages/index")//对应的vue组件
},
{
name:'订单',
disabled:false,
path:'order',
component:()=>import("@/pages/order"),
children:[
{
name:'历史订单',
disabled:true,
},
{
name:'进行中订单',
disabled:false,
path:'orderNew',
component:()=>import("@/pages/order/new"),
},
{
name:'订单详情',
disabled:false,
path:'orderDetails',
component:()=>import("@/pages/order/details"),
},
]
},
{
name:'我的',
disabled:true,
children:[
{
name:'我的钱包',
disabled:true,
},
{
name:'我的信息',
disabled:true,
},
]
},
];
//将菜单添加至vuex,供菜单组件展示使用
this.setMenus(menuArr);
//遍历匹配生成后的菜单树(此树两层,如果是四层以及以上可以考虑递归),生成router树
var routeTree = [];
for(var i = 0 ; i < menuArr.length ; i++){
if(!menuArr[i].disabled){
if(menuArr[i].children){
var children = [];
for(var j = 0 ; j < menuArr[i].children.length ; j++){
if(!menuArr[i].children[j].disabled){
children.push({
path: menuArr[i].children[j].path,
name: menuArr[i].children[j].path,
component: menuArr[i].children[j].component,
})
}
}
if(children.length){
children.push({
path: '/',
redirect: children[0].path
})
children.push({
path: '*',
redirect: children[0].path
})
}
routeTree.push({
path: '/' + menuArr[i].path,
component: menuArr[i].component,
children
})
}else{
routeTree.push({
path: '/' + menuArr[i].path,
name: '/' + menuArr[i].path,
component: menuArr[i].component,
})
}
}
}
if(routeTree.length){
routeTree.push({
path: '/',
redirect: routeTree[0].path
})
routeTree.push({
path: '*',
redirect: routeTree[0].path
})
}else{
routeTree.push({
path: '/fail',
name: 'fail',
component: ()=>import("@/components/fail")
})
routeTree.push({
path: '/',
redirect: '/fail'
})
routeTree.push({
path: '*',
redirect: '/fail'
})
}
//注册路由
this.$router.addRoutes(routes)
//路由注册完成后跳转
if(routeTree.length){
this.$router.push({
path: routeTree[0].path
})
}else{
this.$router.push({
path: '/fail'
})
}
},1000)
},
methods:{
...mapActions({
setMenus: 'setMenus'
}),
}
}