vue3递归实现动态菜单

效果图
在这里插入图片描述

RecursionMenu.vue

<script setup lang="ts">
import { defineProps, toRef } from "vue";
const props = defineProps({
  data: Array,
});
const data = toRef(props, "data");
</script>

<template>
  <template v-for="(item, index) in data" :key="index">
    <template v-if="!item.meta.hidden">
      <el-sub-menu
        popper-class="MypopperClass"
        :style="{ '--color': '#2BAFAE' }"
        v-if="item.children && item.children.length > 0"
        :index="item.path"
        :key="item.path"
      >
        <template #title>
          <el-icon color="#ffffff">
            <i class="iconfont clm-renyuanguanli"></i>
          </el-icon>
          <span>{{ item.meta.title }}</span></template
        >
        <RecursionMenu :data="item.children"></RecursionMenu>
      </el-sub-menu>
      <el-menu-item v-else :index="item.path" :key="item.path">
        <el-icon color="#ffffff">
          <i class="iconfont clm-renyuanguanli"></i>
        </el-icon>
        <template #title>{{ item.meta.title }}</template></el-menu-item
      >
    </template>
  </template>
</template>

<!-- <script></script> -->

layoutAside.vue

<script lang="ts" setup>
import { useRoute, useRouter } from "vue-router";
import RecursionMenu from "@/components/RecursionMenu";
const route = useRoute();
const router = useRouter();
</script>
<template>
  <el-menu
    class="mymenu el-menu-vertical-demo"
    router
    :default-active="route.path"
    collapse-transition
    show-timeout
    hide-timeout
    text-color="#ffffff"
    :style="{ '--color': '#2BAFAE' }"
  >
    <el-menu-item index="/home">
      <el-icon color="#ffffff">
        <i class="iconfont clm-renyuanguanli"></i>
      </el-icon>
      <template #title>{{ "首页" }}</template></el-menu-item
    >
    <el-menu-item index="/DisplayPage">
      <el-icon color="#ffffff">
        <i class="iconfont icon-renyuanguanli"></i>
      </el-icon>
      <template #title>{{ "闭环展示" }}</template></el-menu-item
    >
    <RecursionMenu :data="router.options.routes"></RecursionMenu>
  </el-menu>
</template>
<style lang="scss">
:root {
  color1: var(--color);
}
.el-menu-vertical-demo:not(.el-menu--collapse) {
  height: calc(100vh - 100px);
  background: var(--color);
}
.mymenu {
  .el-menu-item.is-active {
    color: var(--el-menu-active-color);
    background: greenyellow;
  }
  .el-sub-menu .el-menu-item.is-active {
    color: var(--el-menu-active-color);
    background: greenyellow;
  }
  .el-menu-item:hover {
    background-color: #c9c7c7;
  }
  .el-sub-menu .el-menu-item:hover {
    background-color: #c9c7c7;
  }

  .el-sub-menu.is-active .el-sub-menu__title {
    border-bottom-color: #c9c7c7;
  }
  .el-sub-menu__title:hover {
    background-color: #c9c7c7;
  }
  .el-sub-menu .el-menu-item {
    height: var(--el-menu-sub-item-height);
    line-height: var(--el-menu-sub-item-height);
    background: var(--color);
  }
  .el-sub-menu {
    background: var(--color);
  }
}
.mymenu.el-menu {
  border-right: solid 1px var(--el-menu-border-color);
  list-style: none;
  position: relative;
  margin: 0;
  padding-left: 0;
  background-color: var(--color);
  box-sizing: border-box;
}
.MypopperClass {
  .el-menu--popup {
    z-index: 100;
    min-width: 200px;
    border: none;
    padding: 5px 0;
    border-radius: var(--el-border-radius-small);
    box-shadow: var(--el-box-shadow-light);
    background: var(--menu-color);
  }
  .el-menu-item.is-active {
    color: var(--el-menu-active-color);
    background: greenyellow;
  }
  .el-sub-menu .el-menu-item.is-active {
    color: var(--el-menu-active-color);
    background: greenyellow;
  }
  .el-menu-item:hover {
    background-color: #c9c7c7;
  }
  .el-sub-menu .el-menu-item:hover {
    background-color: #c9c7c7;
  }

  .el-sub-menu.is-active .el-sub-menu__title {
    border-bottom-color: #c9c7c7;
  }
  .el-sub-menu__title:hover {
    background-color: #c9c7c7;
  }
  .el-sub-menu .el-menu-item {
    height: var(--el-menu-sub-item-height);
    line-height: var(--el-menu-sub-item-height);
    background: var(--color);
  }
  .el-sub-menu {
    background: var(--color);
  }
}
</style>

路由文件

import { createRouter, createWebHistory } from "vue-router";
import Layout from "@/views/Layout/layoutIndex.vue";
export const constantRoutes = [
  {
    path: "/",
    component: Layout, // 这是一个框架组件,顶部和侧边栏会固定加载
    redirect: "/home", // 重定向的就是中间的内容部分
    meta: {
      title: "首页",
      icon: "iconfont clm-renyuanguanli",
      hidden: true,
      keepAlive: false,
    },
    children: [
      {
        path: "/home",
        component: () => import("@/views/homeIndex/homeIndex.vue"),
        name: "home",
        meta: {
          title: "首页",
          icon: "iconfont clm-renyuanguanli",
          hidden: false,
          keepAlive: false,
        },
      },
    ],
  },
  {
    path: "/show",
    component: Layout, // 这是一个框架组件,顶部和侧边栏会固定加载
    redirect: "/DisplayPage", // 重定向的就是中间的内容部分
    meta: {
      title: "闭环展示",
      icon: "iconfont clm-renyuanguanli",
      hidden: true,
      keepAlive: false,
    },
    children: [
      {
        path: "/DisplayPage",
        component: () => import("@/views/DisplayPage/DisplayPage.vue"),
        name: "DisplayPage",
        meta: {
          title: "闭环展示",
          icon: "iconfont clm-renyuanguanli",
          hidden: false,
          keepAlive: false,
        },
      },
    ],
  },
  {
    path: "/config",
    component: Layout, // 这是一个框架组件,顶部和侧边栏会固定加载
    redirect: "/oneTem", // 重定向的就是中间的内容部分
    meta: {
      title: "闭环配置",
      icon: "iconfont clm-renyuanguanli",
      hidden: false,
      keepAlive: false,
    },
    children: [
      {
        path: "/oneTem",
        component: () => import("@/views/config/oneTem.vue"),
        name: "oneTem",
        meta: {
          title: "单次临时医嘱",
          icon: "iconfont clm-renyuanguanli",
          hidden: false,
          keepAlive: false,
        },
      },
      {
        path: "/longTem",
        component: () => import("@/views/config/longTem.vue"),
        name: "longTem",
        meta: {
          title: "长期医嘱",
          icon: "iconfont clm-renyuanguanli",
          hidden: false,
          keepAlive: false,
        },
      },
      {
        path: "/manyTem",
        component: () => import("@/views/config/manyTem.vue"),
        name: "manyTem",
        meta: {
          title: "多次临时医嘱",
          icon: "iconfont clm-renyuanguanli",
          hidden: false,
          keepAlive: false,
        },
      },
    ],
  },
];

const scrollBehavior = function (to: any, from: any, savedPosition: any) {
  // savedPosition 会在你使用浏览器前进或后退按钮时候生效
  // 这个跟你使用 router.go() 或 router.back() 效果一致
  // 这也是为什么我在 tab 栏结构中放入了一个 点击回退 的按钮
  if (savedPosition) {
    return savedPosition;
  } else {
    // 如果不是通过上述行为切换组件,就会让页面回到顶部
    return { x: 0, y: 0 };
  }
};

const router = createRouter({
  history: createWebHistory(),
  scrollBehavior: scrollBehavior,
  routes: constantRoutes,
});

export default router;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值