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 @ 2023-04-23 15:02  Li_pk  阅读(2820)  评论(0编辑  收藏  举报