困扰的问题之一,就是根据后台返回的菜单动态生成路由。
需要实现的效果
后端返回菜单格式:
{
“id”:45,
“text”:“项目管理”,
…
“children”:[
{
“id”:47,
“text”:“xx管理”,
“pid”:45,
“leaf”:true,
},{
}
]
},
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200311101856785.png
功能点:登录之后请求当前账号有权限的菜单,顶部为主菜单,左侧为对应主菜单下的子菜单
根据菜单树动态生成路由,然后通过addRoutes添加路由。
解决的问题:刷新之后添加的路由会消失
//router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import store from '@/store'
import login from '@/view/Login.vue'
//解决Element-ui 点击多次路由会报错:NavigationDuplicated {_name: “NavigationDuplicated”, name: “NavigationDuplicated”}
const originalPush = Router.prototype.push;
Router.prototype.push = function push(location) {
return originalPush.call(this, location).catch(err => err)
}
Vue.use(Router)
let router = new Router({
routes: [{
path: '/login',
name: 'login',
meta: {
requireAuth: false
},
component: login
}]
})
// 拦截登录,token验证
router.beforeEach((to, from, next) => {
if (to.meta.requireAuth === undefined) {
//判断是否登录
if (store.state.user.isLogin) {
next()
} else {
next({
path: '/login'
})
}
} else {
next()
}
})
export default router
//登录点击事件 登录成功之后
//login.js
this.setMenuAction().then(res => {
var routes = [],
menu = res.data;
routes = routes.concat(generateRouter(menu, []));
routes = handleRoute.mergeRoutes(routes);
// 防止重复配置相同路由
if (this.$router.options.routes.length <= 1) {
this.$router.addRoutes(routes);
// this.$router不是响应式的,所以手动将路由元注入路由对象
this.$router.options.routes.push(routes);
}
});
//vuex store.js
//存储menu和当前子菜单
setMenuAction(context, params) {
return new Promise((resolve, reject) => {
getMenuTree(params).then(result => {
context.commit('setMenu', result.data);
context.commit('setCurrentMenu',result.data[0].children);
resolve(result);
})
})
}
//common.js
//根据菜单生成一个routes数组 具体处理规则根据自己项目处理
export function generateRouter(data = [], router) {
for (let i = 0; i < data.length; i++) {
if (data[i].leaf) {
var path = 'view/'+data[i].identifier.replace(/\_/g,'/');
router.push({
name: data[i].identifier,
path: path,
component: resolve => require(['@/' + path + '.vue'], resolve)
});
} else {
generateRouter(data[i].children, router);
}
}
console.log(router)
return router;
}
//合并本地路由与远程路由
//本地路由,具体根据项目配置
const routes = [{
path: '/',
name: 'home',
component: (resolve) => require(['@/view/Main.vue'], resolve),
children: []
}]
export default {
/**
* 合并远程路由到本地路由
* @param: subList [Array] 远程路由列表
* @param: routes [Array] 本地路由列表
* */
mergeRoutes(subs) {
if (subs) {
// var routeArr = generateRouter(subs, []);
routes[0].children = subs;
}
console.log(routes)
return routes;
}
}
//刷新之后路由消失的问题 登录的时候将路由或者菜单存储到本地 在App.vue
//这里是直接去拿了存储在store里面的menu又生成了一次routes然后添加 更简单的做法是直接将路由存储去获取
export default {
name: 'App',
computed: {
...mapGetters(['isLogin', 'routeList', 'menu'])
},
created() {
if (this.$router.options.routes.length <= 1 && this.$store.state.menu.routeList.length) {
var routes = [],
menu = this.menu ? this.menu : [];
routes = routes.concat(generateRouter(menu ? menu : [], []));
routes = handleRoute.mergeRoutes(routes);
this.$router.addRoutes(routes);
this.$router.options.routes.push(routes);
}
}
};
差不多就到这啦,就当自己的一个笔记啦。能力问题,写的不够优化的地方大家多多包涵、指正。