创建Menu数据库表
CREATE TABLE `menu` (
`menu_id` int NOT NULL AUTO_INCREMENT COMMENT '菜单编号',
`menu_name` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '菜单名称',
`menu_title` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '菜单标题',
`menu_path` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '菜单路径',
`menu_icon` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '菜单图标',
`menu_parent_id` int NULL DEFAULT NULL COMMENT '菜单父级编号',
`menu_order` int NULL DEFAULT NULL COMMENT '菜单排序',
PRIMARY KEY (`menu_id`) USING BTREE
)
添加数据
后端处理数据
第一步,获取menu表中的所有数据
<select id="selectAllMenu" resultMap="BaseResultMap">
SELECT
<include refid="AllColumn"></include>
FROM `menu`
</select>
第二步,对Menu实体类需要做一些修改,需要增加一个children成员变量,用来存放当前菜单的所有子级菜单信息
package com.zero.springbootmall.entity;
import java.util.List;
public class Menu {
private Integer menuId;
private String menuName;
private String menuTitle;
private String menuPath;
private String menuIcon;
private Integer menuParentId;
private Integer menuOrder;
private List<Menu> children;
public List<Menu> getChildren() {
return children;
}
public void setChildren(List<Menu> children) {
this.children = children;
}
public Integer getMenuId() {
return menuId;
}
public void setMenuId(Integer menuId) {
this.menuId = menuId;
}
public String getMenuName() {
return menuName;
}
public void setMenuName(String menuName) {
this.menuName = menuName == null ? null : menuName.trim();
}
public String getMenuTitle() {
return menuTitle;
}
public void setMenuTitle(String menuTitle) {
this.menuTitle = menuTitle == null ? null : menuTitle.trim();
}
public String getMenuPath() {
return menuPath;
}
public void setMenuPath(String menuPath) {
this.menuPath = menuPath == null ? null : menuPath.trim();
}
public String getMenuIcon() {
return menuIcon;
}
public void setMenuIcon(String menuIcon) {
this.menuIcon = menuIcon == null ? null : menuIcon.trim();
}
public Integer getMenuParentId() {
return menuParentId;
}
public void setMenuParentId(Integer menuParentId) {
this.menuParentId = menuParentId;
}
public Integer getMenuOrder() {
return menuOrder;
}
public void setMenuOrder(Integer menuOrder) {
this.menuOrder = menuOrder;
}
@Override
public String toString() {
return "Menu{" +
"menuId=" + menuId +
", menuName='" + menuName + '\'' +
", menuTitle='" + menuTitle + '\'' +
", menuPath='" + menuPath + '\'' +
", menuIcon='" + menuIcon + '\'' +
", menuParentId=" + menuParentId +
", menuOrder=" + menuOrder +
", children=" + children +
'}';
}
}
第三步,对获取到的所有菜单数据进行遍历,通过递归的方式给所有menuParentId为0的菜单的children赋值。最后通过流的方式过滤menuList集合,将menuList中menuParentId为0的菜单作为结果返回给前端。
@Override
public Result queryMenu() {
List<Menu> menuList = menuMapper.selectAllMenu();
for (Menu menu : menuList) {
if (Objects.equals(menu.getMenuParentId(),0)){ //当前菜单为一级菜单
List<Menu> children = getAllChildren(menu.getMenuId());
menu.setChildren(children);
}
}
Stream<Menu> menuStream = menuList.stream().filter(item -> item.getMenuParentId() == 0);
List<Menu> collect = menuStream.collect(Collectors.toList());
System.out.println("++===>>>"+collect);
return Result.success(collect);
}
private List<Menu> getAllChildren(Integer menuId) {
List<Menu> menus = menuMapper.selectMenuByParentId(menuId);
if (Objects.isNull(menus) || Objects.equals(menus.size(),0) ) return null;
for (Menu menu : menus) {
getAllChildren(menu.getMenuId());
}
return menus;
}
前端获取数据渲染
首先,去ElementPlus官网去复制Menu组件的相关代码,并做一些修改。
<el-row class="tac">
<el-col :span="24">
<el-menu
class="el-menu-vertical-demo"
:default-active="currentRouter"
text-color="#fff"
:collapse="isCollapse"
@select="handleSelect"
router
style="--el-menu-bg-color: #304156; --el-menu-hover-bg-color: rgb(38, 52, 69);"
>
<MenuTree :menuList="menuData"></MenuTree>
</el-menu>
</el-col>
</el-row>
<script setup>
import {onMounted, ref} from 'vue';
import { useRouter } from 'vue-router';
import {get,post} from '../api/api.js'
import MenuTree from './MenuTree.vue'
const router = useRouter();
const currentRouter = ref()
const menuData = ref([])
onMounted(()=>{
getMenuData()
})
const getMenuData = async()=>{
let result = await get("/menu/queryMenu")
menuData.value = result.data
console.log(menuData.value); // 打印后端传来的数据
}
const handleSelect=(index)=>{
router.push(index); // 当选中某菜单时进行路由跳转
}
</script>
其次,创建MenuTree组件,通过父传子的方式,将后端传来的数据传给子组件,交给子组件去渲染。
<template>
<div>
<template v-for="item in props.menuList" :key="item.meunId">
<!-- 分为两种方式渲染:有子菜单和没有子菜单-->
<el-sub-menu :index="String(item.menuPath)" v-if="item.children">
<template #title>
<span>{{ item.menuTitle }}</span>
</template>
<!-- 有子菜单的继续遍历(递归)-->
<MenuTree :menuList="item.children"></MenuTree>
</el-sub-menu>
<!-- 没有子菜单 -->
<el-menu-item :index="String(item.menuPath)" v-if="!item.children">
<span>{{ item.menuTitle }}</span>
</el-menu-item>
</template>
</div>
</template>
<script setup >
import { defineProps, onMounted,computed } from 'vue'
const props = defineProps(['menuList'])
onMounted( () => {
console.log(props);
})
</script>
<style></style>
最后,在index.js文件中配置相对应的路由,就可以实现跳转了。