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中进行布局页面,设置三个组件
- menu菜单
- tabbar导航栏 --> 面包屑
- main 内容展示区域
js
<router-view></router-view>
我们将路由出口标签放在main组件中
meta为路由元信息,可以设置属性来控制路由的显示与隐藏和icon图标
进入正题
先展示一下组件嵌套关系,切记el-menu标签(element-ui)是放在layout中的index.vue中的,因为这里需要使用到递归组件,需要传递props属性
- menu组件中引入route.js中的路由数据。
- 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为父组件传递进来的数据。
组件递归需要注意的点:
- 递归组件必须有name属性,并且name的值必须和父组件引入组件时命名相同
- 如果在vue3中,setup写法中没有name属性,需要使用vue2的形式重命名才能进行递归