Vue后台获取路由信息

模拟后台返回路由JSON数据
menudata.js
java
export const menuRouterMap = [
{name:'menu', path: '/home/menu',compPath:'components/Menu'}
]
常量路由文件数据
constant.js
java
import HelloWorld from '@/components/HelloWorld'
export const constantRouterMap = [
{
path: '/HelloWorld',
name: 'HelloWorld',
}
]
/router/index.js
java
import Vue from 'vue'
import Router from 'vue-router'
import {constantRouterMap} from './constant.js'
Vue.use(Router)
const router = new Router({
routes: constantRouterMap
})
router.beforeEach((to,from,next)=>
{
console.log('to='+to.path+",from="+from.path);
next();
})
router.afterEach(() => {
console.log('afterEach ... ');
})
export default router
/router/getrouter.js生成路由树状结构
java
import Vue from 'vue'
import store from '@/store'
import router from './index.js'
import MainLayout from '@/layout/MainLayout'
import { menuRouterMap } from "@/router/menudata"
//系统首页路由
//生成路由对象数据,data是从后台检索菜单列表数据
function createRouter(data) {
//PC端功能路由,展示组件使用MainLayout
let dataPc = [];
for(var i=0;i<data.length;i++)
{
dataPc.push(data[i]);
}
let indexRouter = [
{
path: '/',
name: 'home',
component:MainLayout,
meta: { title: '首页' },
children: [
...createRouterFromMenu(dataPc)
]
}
]
return indexRouter;
}
//根据后台获取的路由配置,装载路由数组
function createRouterFromMenu (data) {
const routers = [];
for (let item of data) {
let component = "";
//function.json中"layouts/RouteView"缺失目录components,此处补充完整
if(item.compPath && item.compPath.indexOf("layouts")>=0){
component = "components/"+item.compPath;
}
else{
component = item.compPath;
}
let componentPath;
//动态加载组件,不需要import导入组件
if(component != null)
componentPath = resolve => require(['@/' + component+'.vue'], resolve);
let menu = {
path:item.path,
name:item.name,
redirect:item.redirect,
component:componentPath,
hidden:item.hidden,
meta: {
title:item.name,
icon:item.icon,
url:item.path,
componentName:item.compName
}
}
if (item.child && item.child.length > 0) {
menu.children = [...createRouterFromMenu( item.child)];
}
routers.push(menu);
}
return routers
}
router.beforeEach((to, from, next) => {
console.log('beforeEach from======'+from.path+',to======'+to.path);
if (store.state.setrouter.functionList.length === 0) {//如果尚未检索后台路由数据
//检索后台路由数据
store.dispatch('GetFunctionList').then(res => {
const funcList = res;
if (funcList != null && funcList != undefined)
{
let menuRoutes = [];
//赋值前端路由实例变量
menuRoutes = createRouter(funcList);
//将后台功能菜单授权路由与常量路由合并
store.dispatch('MergeMenuRouter',{ menuRoutes }).then(() => {
//addRoutes是vue-router定义的方法,用于添加路由信息
router.addRoutes(store.state.setrouter.addRouters)
const redirect = decodeURIComponent(from.query.redirect || to.path)
console.log('to.path='+to.path+',redirect='+redirect);
if (to.path === redirect) {
next({ ...to, replace: true })
} else {
next({ path: redirect })
}
})
}
else
{
next();
}
})
.catch((e) => {
console.log('2################################'+e);
next({ path: '/user/login', query: { redirect: to.fullPath,error:e } })
})
}
else
{
next();
}
})
router.beforeResolve((to, from, next) => {
console.log('beforeResolve ......................');
next();
})
router.afterEach(() => {
console.log('afterEach .......................');
})
引入Vuex组件
/store/index.js
java
import Vue from 'vue'
import Vuex from 'vuex'
import setrouter from './setrouter'
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
setrouter
},
state: {
},
mutations: {
},
actions: {
},
getters: {
setrouter: state => state.setrouter.setrouter,
}
})
/store/setrouter.js模拟Ajax请求动态路由数据,合并静态路由与动态路由数据
java
import { constantRouterMap } from "@/router/constant"
import { menuRouterMap } from "@/router/menudata"
const setrouter = {
state: {
routers: constantRouterMap,
addRouters: [],
functionList: [],
},
mutations: {
SET_NAME: (state, data) => {
state.name = data;
console.log('子模块---------------------SET_NAME2');
},
//将后台获取路由合并到常量路由对象
SET_ROUTERS: (state, data) => {
state.addRouters = data
state.routers = constantRouterMap.concat(data)
},
SET_FUNCTIONLIST: (state, functionList) => {
state.functionList = functionList
},
},
actions: {
// 获取当前用户菜单权限
GetFunctionList({ commit, state, getters, rootState, rootGetters }) {
return new Promise((resolve, reject) => {
resolve(menuRouterMap);
commit({
type:'SET_FUNCTIONLIST', functionList:menuRouterMap
});
commit('SET_NAME','Module commit');
})
},
//将后台功能菜单授权路由与常量路由合并
MergeMenuRouter(context, routes) {
return new Promise(resolve => {
let routelist = routes.menuRoutes;
context.commit('SET_ROUTERS', routelist)
resolve()
})
}
}
}
export default setrouter
路由视图文件
HkLayout.vue
html
import { constantRouterMap } from "@/router/constant"
import { menuRouterMap } from "@/router/menudata"
const setrouter = {
state: {
routers: constantRouterMap,
addRouters: [],
functionList: [],
},
mutations: {
SET_NAME: (state, data) => {
state.name = data;
console.log('子模块---------------------SET_NAME2');
},
//将后台获取路由合并到常量路由对象
SET_ROUTERS: (state, data) => {
state.addRouters = data
state.routers = constantRouterMap.concat(data)
},
SET_FUNCTIONLIST: (state, functionList) => {
state.functionList = functionList
},
},
actions: {
// 获取当前用户菜单权限
GetFunctionList({ commit, state, getters, rootState, rootGetters }) {
return new Promise((resolve, reject) => {
resolve(menuRouterMap);
commit({
type:'SET_FUNCTIONLIST', functionList:menuRouterMap
});
commit('SET_NAME','Module commit');
})
},
//将后台功能菜单授权路由与常量路由合并
MergeMenuRouter(context, routes) {
return new Promise(resolve => {
let routelist = routes.menuRoutes;
context.commit('SET_ROUTERS', routelist)
resolve()
})
}
}
}
export default setrouter
MainLayout.vue
html
<template>
<div>
<router-view></router-view>
</div>
</template>
<style>
.el-container{
top:0px;
}
.el-header {
background-color: #B3C0D1;
color: #333;
line-height: 60px;
}
.el-aside {
color: #333;
overflow-y: auto;
}
</style>
<script>
export default {
mounted() {
}
}
</script>
`
修改main.js文件,首页跳转到HkLayout
`
html
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import HkLayout from './layout/HkLayout'
import router from './router'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import './router/getrouter.js'
import axios from 'axios'
Vue.use(ElementUI)
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { HkLayout },
template: '<HkLayout/>'
})