前言
大家好,我是腾讯云开发者社区的 Front_Yue,本篇文章将解决如何将数据库中菜单信息表转化为Vue路由信息列表。
在构建一个基于 Vue.js 的单页应用时,我们经常需要根据后端数据库中的系统菜单来动态生成前端路由。这样做的好处是,当后端菜单结构发生变化时,前端路由可以自动更新,无需手动修改代码。本文将介绍如何在 Vue 中实现查询数据库系统菜单并将其转化为 router 路由格式参数。
正文内容
一、服务端准备工作
1. 菜单信息表数据库设计
为了储存菜单信息,我们需要设计一个用于存储菜单信息的数据库表时,我们需要考虑菜单的基本属性以及可能的关联关系。以下是一个简单的菜单信息表数据库设计示例:
2. 获取菜单信息表接口
为了使客户端能够请求到数据库中的菜单信息,我们还需要设计查询菜单表接口,以下接口仅作参考。
代码语言:java复制@Tag(name = "菜单权限表接口")
@RestController
@RequestMapping("/system/menu")
public class MenuController extends BaseController {
@Autowired
private IMenuService menuService;
@Operation(summary ="查询菜单权限表")
@GetMapping("/list")
public AjaxResult list(Menu menu){
List<Menu> list= menuService.list(menu);
return success(list);
}
@Operation(summary ="分页查询菜单权限表")
@GetMapping("/page")
public AjaxResult page(Page<Menu> page,Menu menu){
IPage<Menu> menuIPage= menuService.page(page, menu);
return success(menuIPage);
}
}
二.、客户端准备工作
1. 安装并引入 axios
为了与后端接口进行通信,我们可以使用 axios 这个流行的 HTTP 客户端库。首先,通过 npm 安装 axios:
代码语言:bash复制npm install axios
然后,在 Vue 组件或 Vuex 中引入 axios:
代码语言:javascript复制import axios from 'axios';
封装请求菜单信息列表api接口
代码语言:js复制import request from '@/utils/request'
/* 查询菜单列表 */
export const listMenu = (params) => {
return request({
url: '/system/menu/list',
method: 'get',
params: params
})
}
2. 请求服务端接口
在 Vue 组件的 created
或 mounted
生命周期钩子中,使用 axios 调用后端接口获取菜单数据:
import { onMounted, reactive, ref } from "vue";
import {listMenu} from "@/api/system/menu";
const tableData = ref([{}]);
const queryParams = reactive({
menuName: null,
menuType: null,
visible: null,
status: null,
});
onMounted(() => {
getMenuList();
});
const getMenuList = async () => {
const res = await listMenu(queryParams);
tableData.value = res.data;
};
经过上述方法,我们得到菜单数据如下:
代码语言:json复制[
{
"createBy": null,
"createTime": null,
"updateBy": null,
"updateTime": null,
"remark": "",
"menuId": 1,
"menuName": "系统管理",
"parentId": 0,
"orderNum": 2,
"path": "system",
"component": "",
"menuType": "M",
"visible": "0",
"status": "0",
"perms": null,
"icon": ""
},
{
"createBy": null,
"createTime": null,
"updateBy": null,
"updateTime": null,
"remark": "",
"menuId": 2,
"menuName": "用户管理",
"parentId": 1,
"orderNum": 1,
"path": "user",
"component": "system/user/index",
"menuType": "C",
"visible": "0",
"status": "0",
"perms": null,
"icon": ""
},
{
"createBy": null,
"createTime": null,
"updateBy": null,
"updateTime": null,
"remark": "",
"menuId": 3,
"menuName": "菜单管理",
"parentId": 1,
"orderNum": 2,
"path": "menu",
"component": "system/menu/index",
"menuType": "C",
"visible": "0",
"status": "0",
"perms": null,
"icon": ""
}
]
三、封装菜单数据转换方法
为了优化代码逻辑,我们可以编写一个函数来将菜单数据转化为符合要求的路由参数,在编写函数之前我们先看看正确的路由格式。
代码语言:json复制[
{
path: "/system",
name:"System",
component: () => import("@/layout/index.vue"),
children: [
{
path: "menu",
name: "Menu",
component: () => import("@/pages/system/menu/index.vue"),
meta: {
title: "菜单",
icon: "menu",
},
},
],
}
]
有了上述目标数据作为参考,我们就可以编写转化函数了,我们需要定义一个menuUntil.js
文件用于我们封装该方法。
- 导入
listMenu
函数,该函数用于查询数据库中的系统菜单数据。
import { listMenu } from "@/api/system/menu";
- 定义
getRouters
函数,该函数是一个异步函数,因为它需要从数据库中获取菜单数据。
export const getRouters = async () => {
- 使用
import.meta.glob
函数获取所有的 Vue 组件,这些组件将作为路由的component
属性。
const modules = import.meta.glob("/src/**/index.vue");
- 调用
listMenu
函数获取系统菜单数据。
const res = await listMenu();
const data = res.data;
- 创建一个名为
resultMap
的 Map 对象,用于存储菜单数据。
const resultMap = new Map();
- 遍历查询到的菜单数据,根据菜单类型(
menuType
)将数据转换为 Vue Router 可识别的路由格式参数,并将结果存储到resultMap
中。
data.forEach((item) => {
if (item.menuType === "M") {
resultMap.set(item.menuId, {
name: item.path.charAt(0).toUpperCase() item.path.slice(1),
path: '/' item.path,
hidden: item.visible == "0" ? false : true,
component: modules[`/src/layout/index.vue`],
meta: {
title: item.menuName,
icon: item.icon || "user",
},
children: [],
});
} else if (item.menuType === "C") {
const parent = resultMap.get(item.parentId);
if (parent) {
parent.children.push({
name: item.path.charAt(0).toUpperCase() item.path.slice(1),
path: item.path,
hidden: item.visible == "0" ? false : true,
component:modules[`/src/pages/${item.component}.vue`],
meta: {
title: item.menuName,
icon: item.icon || "user",
},
});
}
}
});
- 将
resultMap
中的值转换为数组并返回。
return Array.from(resultMap.values());
};
完整代码如下:
代码语言:js复制import { listMenu } from "@/api/system/menu";
export const getRouters = async () => {
const modules = import.meta.glob("/src/**/index.vue");
const res = await listMenu();
const data = res.data;
const resultMap = new Map();
data.forEach((item) => {
if (item.menuType === "M") {
resultMap.set(item.menuId, {
name: item.path.charAt(0).toUpperCase() item.path.slice(1),
path: '/' item.path,
hidden: item.visible == "0" ? false : true,
component: modules[`/src/layout/index.vue`],
meta: {
title: item.menuName,
icon: item.icon || "user",
},
children: [],
});
} else if (item.menuType === "C") {
const parent = resultMap.get(item.parentId);
if (parent) {
parent.children.push({
name: item.path.charAt(0).toUpperCase() item.path.slice(1),
path: item.path,
hidden: item.visible == "0" ? false : true,
component:modules[`/src/pages/${item.component}.vue`],
meta: {
title: item.menuName,
icon: item.icon || "user",
},
});
}
}
});
return Array.from(resultMap.values());
};
四、在Router中使用该方法
对于Vue3,我们首先在 src/router
目录下创建index.js
文件用于初始化路由相关信息,创建路由,定义路由类型。
import { createRouter, createWebHistory } from "vue-router";
import routes from "./routes"; // 专门用来处理路由列表
const router = createRouter({
history: createWebHistory(),
routes: routes
})
export default router
在该目录下我们在创建一个routes.js
文件,用于存储路由信息,在次文件中,我们使用上述定义的方法,将其转化的路由与基本路由合并抛出,用于页面显示。
// 引入封装的`menuUntil`方法
import { getRouters } from "@/utils/menuUntil";
const routes = await getRouters();
const baseRoute = [
{
path: "/",
component: () => import("@/layout/index.vue"),
redirect: "/index",
children: [
{
path: "/index",
name: "index",
component: () => import("@/pages/index/index.vue"),
meta: {
title: "首页",
icon: "label",
},
},
],
},
{
path: "/login",
name: "login",
component: () => import("@/pages/login/index.vue"),
meta: {
title: "登录",
icon: "label",
},
},
];
export default [...baseRoute,...routes];
上述执行getRouters
方法后,得到的数据如下:
[
{
"name": "System",
"path": "/system",
"hidden": false,
"meta": {
"title": "系统管理",
"icon": "user"
},
"children": [
{
"name": "User",
"path": "user",
"hidden": false,
"meta": {
"title": "用户管理",
"icon": "user"
}
},
{
"name": "Menu",
"path": "menu",
"hidden": false,
"meta": {
"title": "菜单管理",
"icon": "user"
}
}
]
}
]
经过以上过程,动态路由到此处理结束,在后续项目代码编写过程中,只需要路由信息添加到数据库表中,不再需要关注路由模块。
总结
本文介绍了如何在 Vue.js 和 Vue Router 中查询数据库系统菜单,通过定义转化数据的函数,并将其转化为 Vue Router 可识别的路由格式参数。通过这种方式,我们可以实现动态生成和渲染导航菜单以及对应的页面内容。
最后,感谢腾讯云开发者社区小伙伴的陪伴,如果你喜欢我的博客内容,认可我的观点和经验分享,请点赞、收藏和评论,这将是对我最大的鼓励和支持。同时,也欢迎大家提出宝贵的意见和建议,让我能够更好地改进和完善我的博客。谢谢!
我正在参与2024腾讯技术创作特训营最新征文,快来和我瓜分大奖!