el-menu递归组件实现多级菜单(vue3+element plus版)

vue2 + element ui版:点击此处

1. 外层菜单组件:

LeftMenu.vue

<template>
<el-menu
:default-active="activeMenu"
router
:class="'menu-left'"
:default-openeds="openedsArr"
text-color="#fff"
>
<LeftSubMenu :menuData="menuData"></LeftSubMenu>
</el-menu>
</template>
<script setup>
import LeftSubMenu from "@/components/LeftSubMenu.vue";
import { computed } from "vue";
import { useRouter } from "vue-router";
const openedsArr = props.menuData.map((item) => {
return item.path;
});
const props = defineProps({
menuData: {
type: Array,
default: [],
},
});
const activeMenu = computed(() => {
const router = useRouter();
const { meta, path } = router.currentRoute.value;
if (meta.matchPath2) {
return meta.matchPath2;
} else {
return path;
}
});
</script>
<style scoped>
.menu-left {
flex: 1;
padding: 0 8px;
border-right: none;
background: none;
}
.menu-left:deep(.el-menu),
.menu-left:deep(.el-sub-menu__title:hover) {
background: none;
}
.menu-left:deep(.el-menu-item),
.menu-left:deep(.el-sub-menu__title) {
height: 36px;
margin-bottom: 4px;
border-radius: 4px;
color: var(--text-main-color) !important;
}
.menu-left:deep(.el-menu-item:hover .icon),
.menu-left:deep(.el-menu-item.is-active .icon) {
filter: invert(100%);
-webkit-filter: invert(100%);
}
.menu-left:deep(.el-menu-item:hover),
.menu-left:deep(.el-menu-item.is-active) {
color: #ffffff !important;
background-color: #243158;
}
</style>

2. 子菜单组件(递归主体):

LeftSubMenu.vue

<template>
<template v-for="item in menuData">
<el-sub-menu
:key="item.path"
v-if="item.children && item.children.length > 0"
:index="item.path"
:class="item.icon ? '' : 'noIcon'"
>
<template #title>
<img
class="icon pd-r-10"
:src="curRoute.indexOf(item.path) != -1 ? item.iconActive : item.icon"
/>
<img class="icon pd-r-10" :src="item.icon" />
<span>{{ item.label }}</span>
</template>
<LeftSubMenu :menuData="item.children"></LeftSubMenu>
</el-sub-menu>
<el-menu-item
:key="item.id"
v-else
:index="item.path"
:disabled="item.disabled"
>
<template #title>
<img class="icon pd-r-10" :src="item.icon" />
<span>{{ item.label }}</span>
</template>
</el-menu-item>
</template>
</template>
<script setup>
import LeftSubMenu from "./LeftSubMenu.vue";
import { computed } from "vue";
import { useRouter } from "vue-router";
const props = defineProps({
menuData: {
type: Array,
default: [],
},
});
const curRoute = computed(() => {
const router = useRouter();
const { path } = router.currentRoute.value;
return path;
});
</script>

3. 使用:

...
<LeftMenu :menuData="menuList"></LeftMenu>
...
const menuList = [
{
title: "菜单一",
path: "/menutest/menu1",
icon: new URL("@/assets/images/icons/icon.png", import.meta.url).href,
iconActive: new URL("@/assets/images/icons/icon_active.png", import.meta.url).href,
children: [
{
title: "子菜单一",
path: "/menutest/menu1/menu1-1",
// disabled: true,
},
{
title: "子菜单二",
path: "/menutest/menu1/menu1-2",
},
],
},
{
title: "菜单二",
path: "/menutest/menu2",
icon: new URL("@/assets/images/icons/icon.png", import.meta.url).href,
iconActive: new URL("@/assets/images/icons/icon_active.png", import.meta.url).href,
children: [
{
title: "子菜单一",
path: "/menutest/menu2/menu2-1",
},
{
title: "子菜单二",
path: "/menutest/menu2/menu2-2",
children: [
{
title: "孙子菜单一",
path: "/menutest/menu2/menu2-2/menu2-1-1",
},
{
title: "孙子菜单二",
path: "/menutest/menu2/menu2-2/menu2-2-2",
},
],
},
{
title: "子菜单三",
path: "/menutest/menu2/menu2-3",
},
],
},
{
title: "菜单三",
path: "/menutest/menu3",
icon: new URL("@/assets/images/icons/icon.png", import.meta.url).href,
iconActive: new URL("@/assets/images/icons/icon_active.png", import.meta.url).href,
},
];

注意vite图片引入的方式

posted @   Li_pk  阅读(3202)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示