Skip to content

仅一级菜单

默认情况和官方示例,菜单都是两级。

那如何能做到仅一级菜单呢?

创建路由文件

我们创建一个仅展示一级菜单 演示的路由文件。

js
// src/router/routes/modules/no-submenu.ts
import { DEFAULT_LAYOUT } from "../base";
import { AppRouteRecordRaw } from "../types";

const NOSUBMENU: AppRouteRecordRaw = {
  path: "/welcome-temp",
  name: "welcome-temp",
  component: DEFAULT_LAYOUT,
  redirect: "/welcome",
  meta: {
    locale: "欢迎页",
    requiresAuth: false,
    icon: "icon-customer-service",
    order: 0,
    hideChildrenInMenu: true,
  },
  children: [
    {
      path: "/welcome",
      name: "welcome",
      component: () => import("@/views/welcome.vue"),
      meta: {
        requiresAuth: true,
        activeMenu: "welcome-temp",
      },
    },
  ],
};

export default NOSUBMENU;

创建页面

vue
<!-- src/views/welcome/index.vue -->
<template>
  <div>👏🏻 欢迎!</div>
</template>

<script setup lang="ts" name="welcome">
console.log(123);
</script>

重启预览

效果如下

参考:

优化

封装方法

这样每次写很繁琐,通过观察可以发现其实都是有规律存在, 我们可以封装个方法。

js
/**
 * 生成不包含子菜单项的菜单
 *
 * @param oldMenu 旧的菜单数据,可以是 AppRouteRecordRaw 数组或单个 AppRouteRecordRaw 对象
 * @returns 生成的新菜单数据
 */
const genNoSubMenuItem = (
  oldMenu: Array<AppRouteRecordRaw> | AppRouteRecordRaw
) => {
  const handler = (item: AppRouteRecordRaw) => {
    return {
      path: `${item.path}-temp`,
      name: `${String(item?.name)}-temp`,
      component: DEFAULT_LAYOUT,
      redirect: item.path,
      meta: {
        locale: "欢迎页",
        requiresAuth: false,
        icon: item.meta?.icon,
        order: item.meta?.order || 0,
        hideChildrenInMenu: true,
      },
      children: [
        {
          ...item,
          meta: {
            ...item.meta,
            requiresAuth: true,
            activeMenu: `${String(item?.name)}-temp`,
          },
        },
      ],
    };
  };
  const isObject = !Array.isArray(oldMenu);
  if (isObject) return handler(oldMenu);
  return oldMenu.map((item) => handler(item));
};

使用

最后我们使用即可,

js
const NOSUBMENU: AppRouteRecordRaw = {
  path: '/welcome',
  name: 'welcome',
  component: () => import('@/views/demo/welcome.vue'),
  meta: {
    order: 0,
    locale: '欢迎',
    requiresAuth: true,
    icon: 'icon-customer-service',
  },
};
export default genNoSubMenuItem(NOSUBMENU);

当然传数组也是可以

js
const NOSUBMENU: Array<AppRouteRecordRaw> = [
  {
    path: '/welcome',
    name: 'welcome',
    component: () => import('@/views/demo/welcome.vue'),
    meta: {
      order: 0,
      locale: '欢迎',
      requiresAuth: true,
      icon: 'icon-customer-service',
    },
  },
  {
    path: '/list',
    name: 'list',
    component: () => import('@/views/demo/list.vue'),
    meta: {
      order: 0,
      locale: '列表',
      requiresAuth: true,
      icon: 'icon-book',
    },
  },
];

export default genNoSubMenuItem(NOSUBMENU);