前言
最近公司重构了一套营业厅的前端页面,可以由于设计的不好,导致各种问题频发,其中我认为设计的最不好的一个就是路由,路由由于使用的还是router.js,文件又大,上千个菜单都配置到一个文件里面,各个团队都有自己的页面,乱七八糟,我理解这样还不如放到数据库,然后根据数据库可以指定路由名、组件名、归属团队等信息,使用的时候根据权限去动态加载路由,而现在是一股脑全部加载进去,导致前端项目卡顿,操作员使用不畅。
1、后端接口返回菜单路径等(和router.js中的格式一样)
2、前端动态渲染
2.1、vuex配置
import Vue from 'vue'
import Vuex from 'vuex'
// vuex状态管理工具
Vue.use(Vuex)
export default new Vuex.Store({
state:{
routes: []
},
mutations:{
initRoutes(state,data) {
state.routes = data;
}
},
actions:{
}
})
2.2、菜单工具类(用于解析后端返回的json菜单)
// 菜单工具类,用于将后端返回的菜单格式化为符合路由写法的格式
import {getRequest} from "./api";
// 加载所有菜单
export const initMenu=(router,store) => {
if (store.state.routes.length > 0) {
return;
}
getRequest("/system/config/menu").then(
data=>{
if (data) {
let fmtRoutes = formatRoutes(data);
router.addRoutes(fmtRoutes);
store.commit('initRoutes', fmtRoutes);
}
}
)
}
export const formatRoutes = (routes) => {
let fmRoutes = [];
routes.forEach(router => {
let {
path,
component,
name,
meta,
iconCls,
children
} = router;
if (children && children instanceof Array) {
children = formatRoutes(children);
}
let fmRouter={
path:path,
name:name,
iconCls:iconCls,
meta:meta,
children:children,
component(resolve) {
if (component.startsWith("Home")) {
require(['../views/'+component+'.vue'],resolve); // 动态导入
} else if (component.startsWith("Emp")) {
require(['../views/emp/'+component+'.vue'],resolve); // 动态导入
} else if (component.startsWith("Per")) {
require(['../views/per/'+component+'.vue'],resolve); // 动态导入
} else if (component.startsWith("Sal")) {
require(['../views/sal/'+component+'.vue'],resolve); // 动态导入
} else if (component.startsWith("Sta")) {
require(['../views/sta/'+component+'.vue'],resolve); // 动态导入
} else if (component.startsWith("Sys")) {
require(['../views/sys/'+component+'.vue'],resolve); // 动态导入
}
}
}
fmRoutes.push(fmRouter)
})
return fmRoutes;
}
2.3 、路由增加前置守卫(用于监听加载)
import Vue from 'vue'
import VueRouter from 'vue-router'
import Login from '../views/Login.vue'
import {initMenu} from "../utils/menus";
import store from "../store";
Vue.use(VueRouter)
// 引入组件
const routes = [
{
path: '/',
name: 'Login',
component: Login,
hidden: true
}
]
const router = new VueRouter({
routes
})
// 引入前置守卫,类似于过滤器,监听操作
router.beforeEach((to, from, next) => {
// 防止刷新页面后菜单未加载,添加前置守卫
if (to.path == '/') {
next();
} else {
initMenu(router,store);
next();
}
})
export default router
2.4、使用
<!--<el-menu @select="menuClick">-->
<el-menu router unique-opened>
<!--之前从路由中获取<el-submenu index="1" v-for="(item,index) in this.$router.options.routes" v-if="!item.hidden" :key="index">-->
<el-submenu :index="index + ''" v-for="(item,index) in routes" v-if="!item.hidden" :key="index">
<template slot="title">
<i class="el-icon-location"></i>
<span>{{item.name}}</span>
<!--<span>test</span>-->
</template>
<el-menu-item-group>
<el-menu-item :index="child.path" v-for="(child,indexj) in item.children" :key="indexj">{{child.name}}</el-menu-item>
<!-- <el-menu-item index="/test1">1</el-menu-item>
<el-menu-item index="/test2">2</el-menu-item>-->
</el-menu-item-group>
</el-submenu>
</el-menu>
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第29天,点击查看活动详情