vue2根据路由动态生成menu菜单

1、需要先获得路由数据

路由数据可以是routes.js中的路由数据,也可以是服务返回的数组

route.js中的数据如下

[ 复制代码
    {
        // 骨架路由/顶层路由
        path: '/',
        redirect: '/home',
        component: () => import('@/layout/index.vue'),
        meta: {
            hidden: true,
            title: '权限管理',
            icon: 'lock',
        },
        children: [
            {
                path: '/home',
                component: () => import('@/views/home/index.vue'),
                meta: {
                    hidden: true,
                    title: '权限管理',
                    icon: 'lock',
                },
            },
        ]
    },
    {
        path: '/name',
        component: () => import('@/layout/index.vue'),
        redirect: '/setting/base',
        meta: {
            hidden: true,
            title: '权限管理',
            icon: 'lock',
        },
        children: [
            {
                path: '/setting/base',
                component: () => import('@/views/product/attr'),
                meta: {
                    hidden: true,
                    title: '权限管理',
                    icon: 'lock',
                },
            }
        ]
    },
    {
        path: '/acl',
        component: () => import('@/layout/index.vue'),
        name: 'Acl',
        redirect: '/acl/user',
        meta: {
            hidden: true,
            title: '权限管理',
            icon: 'lock',
        },
        children: [
            {
                path: '/acl/user',
                component: () => import('@/views/acl/user/index.vue'),
                name: 'User',
                meta: {
                    hidden: true,
                    title: '用户管理',
                    icon: 'user',
                },
            },
            {
                path: '/acl/role',
                component: () => import('@/views/acl/role/index.vue'),
                name: 'Role',
                meta: {
                    hidden: true,
                    title: '角色管理',
                    icon: 'userFilled',
                },
            },
            {
                path: '/acl/permission',
                component: () => import('@/views/acl/permission/index.vue'),
                name: 'Permission',
                meta: {
                    hidden: true,
                    title: '菜单管理',
                    icon: 'monitor',
                },
            },
        ],
    },
    {
        path: '/product',
        name: 'Product',
        component: () => import('@/layout/index.vue'),
        meta: {
            title: '商品管理',
            icon: 'goods',
            hidden: true,
        },
        redirect: '/product/trademark',
        children: [
            {
                path: '/product/trademark',
                name: 'Trademark',
                component: () => import('@/views/product/trademark/index.vue'),
                meta: {
                    title: '品牌管理',
                    icon: 'collectionTag',
                    hidden: true,
                }
            },
            {
                path: '/product/attr',
                name: 'Attr',
                component: () => import('@/views/product/attr/index.vue'),
                meta: {
                    title: '属性管理',
                    icon: 'goods',
                    hidden: true,
                }
            },
        ]
    },
    {

        path: '/login',
        name: 'login',
        component: () => import('@/views/login/index.vue'),
        meta: {
            title: '属性管理',
            icon: 'SwitchFilled',
            hidden: false,
        }
    },
    {
        // 404路由
        path: '*',
        name: '404',
        component: () => import('@/views/404/index.vue'),
        meta: {
            title: '属性管理',
            icon: 'SwitchFilled',
            hidden: false,
        }
    }
]

其中layout为骨架组件,大部分需要展示的组件都是layout的子组件,在layout中进行布局页面,设置三个组件

  1. menu菜单
  2. tabbar导航栏 --> 面包屑
  3. main 内容展示区域
js 复制代码
<router-view></router-view>
我们将路由出口标签放在main组件中

meta为路由元信息,可以设置属性来控制路由的显示与隐藏和icon图标

进入正题

先展示一下组件嵌套关系,切记el-menu标签(element-ui)是放在layout中的index.vue中的,因为这里需要使用到递归组件,需要传递props属性

  1. menu组件中引入route.js中的路由数据。
  2. menu组件中使用el-menu标签,中的子标签。
javascript 复制代码
import routes from "@/xxx/xx/routes.js"

<div>
    <template v-for="item in menuList">
      <!-- 路由没有子路由 -->
      <template v-if="!item.children">
        <!-- 通过路由元信息:meta,控制路由是否动态生成 -->
        <el-menu-item :index="item.path" :key="item.id" v-if="item.meta.hidden">
          <!-- icon图标 -->
          <i :class="item.icon"></i>
          <!-- menu菜单名 -->
          <span slot="title">{{ item.meta.title }}</span>
        </el-menu-item>
      </template>

      <!-- 路由有子路由路由 且只有一个子路由,这个可有可无 -->
        
      <template v-if="item.children && item.children.length == 1">
        <el-menu-item :index="item.path" :key="item.id" v-if="item.meta.hidden">
          <!-- icon图标 -->
          <i :class="item.icon"></i>
          <!-- menu菜单名 -->
          <span slot="title">{{ item.meta.title }}</span>
        </el-menu-item>
      </template>

      <!-- 路由有子路由路由 且有多个子路由 -->
      <template v-if="item.children && item.children.length > 1">
        <el-submenu :index="item.path" :key="item.id" v-if="item.meta.hidden">
          <template slot="title">
            <!-- icon图标 -->
            <i :class="item.icon"></i>
            <!-- menu菜单名 -->
            <span slot="title">{{ item.meta.title }}</span>
          </template>

          <!-- submenu里面的内容通过组件递归生成 -->
          <menuInfo :menuList="item.children"></menuInfo>
        </el-submenu>
      </template>
    </template>
  </div>

<script>
export default {
  name: "menuInfo",
  data() {
    return {};
  },
  props: ["menuList"],
};
</script>

其中在vue2中template标签在使用v-for时不能绑定关键字key,那么我们就把key设置到el-menu-item标签身上。一般情况下不使用el-menu-item-group标签,el-menu-item标签够用。 menulist为父组件传递进来的数据。

组件递归需要注意的点:

  1. 递归组件必须有name属性,并且name的值必须和父组件引入组件时命名相同
  2. 如果在vue3中,setup写法中没有name属性,需要使用vue2的形式重命名才能进行递归
相关推荐
JavaGuide1 小时前
NVIDIA 又开源了!这次给 AI Agent 加上权限管控
前端·后端
excel1 小时前
prisma 如何处理数据库竞态
前端·数据库·后端
莪_幻尘2 小时前
Skill 体检:30 个 Skill 全凭感觉?体检器先自曝了 8 个“假 0 分
前端·人工智能·llm
风骏时光牛马2 小时前
AI模型综合能力评测:性能、指令遵循与多场景实测对比
前端
Frag0ut2 小时前
Chrome与Chromium内核浏览器在Windows 11上的新特性全景解析
前端·chrome·windows·web安全·chromium·gemini ai·playready drm
hiahiahia1233 小时前
实现完整 Tool Dispatcher
开发语言·前端
IT_陈寒3 小时前
Java线程池这破玩意,差点让我周末加班排查到凌晨
前端·人工智能·后端
Mr_Mao4 小时前
告别选型困难!集 VueUse、ahooks、Mantine 于一身:286 个 Hook 的 ReaUse 来了
前端·javascript·react.js
泡海椒5 小时前
趋势分析报表:jquick-pdf折线图PDF生成实战
java·大数据·运维·服务器·前端·pdf
默_笙5 小时前
🚙 一条腿走路会摔:ES 关键词检索、混合召回与 ReRank 裁判
前端·javascript