nuxt3中使用el-menu和jsx实现无限递归菜单

74 阅读1分钟

效果图

screenshots.gif

所有代码

<template>
  <div class="y_aside">
    <el-scrollbar>
      <client-only>
        <el-menu :default-active="data.defaultActive" :collapse="data.isCollapse" class="el-menu-vertical-demo">
          <YMenu v-for="item in data.menus" :menu="item" :key="item.path" />
        </el-menu>
      </client-only>
    </el-scrollbar>
  </div>
</template>

<script setup lang="jsx">
import {
  Menu as IconMenu,
} from '@element-plus/icons-vue'

const router = useRouter();
const route = useRoute();
const data = reactive({
  isCollapse: false,
  defaultActive: "/main/supplier",
  menus: [
    {
      name: "供应商",
      path: "/main/supplier",
    },
    {
      name: "客户中心",
      path: "/main/customer",
      children: [
        {
          name: "问答库",
          path: "/main/customer/question",
        },
        {
          name: "问答库1",
          path: "/main/customer/question1",
          children: [
            {
              name: "hhh",
              path: "/main/customer/question1/hhh"
            }
          ]
        }
      ]
    },
    {
      name: "工作计划",
      path: "/main/workplan"
    },
  ]
});

const YMenu = (props) => {
  const { menu } = props

  // 含子菜单的折叠菜单
  if (menu.children && menu.children instanceof Array && menu.children.length) {
    const subMenuSlots = {
      title: () => (
        <>
          <ElIcon><IconMenu /></ElIcon>
          <span>{menu.name}</span>
        </>
      )
    }
    return (
      <ElSubMenu v-slots={subMenuSlots} index={menu.path}>
        {menu.children.map(item => <YMenu menu={item} />)}
      </ElSubMenu>
    )
  }

  // 不含子菜单的菜单
  const menuItemSlots = {
    title: () => <span>{menu.name}</span>
  }
  return (
    <ElMenuItem v-slots={menuItemSlots} onClick={() => toUrl(menu.path)} index={menu.path}>
      <ElIcon><IconMenu /></ElIcon>
    </ElMenuItem>
  )
}

const toUrl = (path) => {
  router.push(path);
};

watch(
  () => route.path,
  (newValue) => {
    data.defaultActive = newValue;
  },
  {
    immediate: true
  }
)

</script>

<style scoped lang="scss">
.y_aside {
  height: 100%;
  display: flex;
  flex-direction: column;
  position: relative;
}

.el-menu-vertical-demo:not(.el-menu--collapse) {
  width: 200px;
  min-height: 400px;
}

:deep(.el-scrollbar) {
  flex: 1;
  background-color: transparent;
}

:deep(.el-menu) {
  flex: 1;
  border-right: 0;
  background-color: transparent;
}

:deep(.el-menu-item.is-active) {
  background: #e7f8f5;
  color: #15BC9C;
}
</style>