前期准备
需要的组件:
layout/index.vue:路由组件,用来整个页面,包括侧边栏、头部、主要内容区域,是根路由所映射的组件。
layout/main-layout.vue:路由组件,用来渲染主要内容区域内的内容,是每个菜单目录的路由所映射的组件,是该目录下路由映射组件的一个容器。
layout/index.vue是根路由所映射的组件,这个组件中的主要内容区域main中放一个路由视图占位符,这样当访问所有根路由的子路由时,都会在index
注意:侧边栏菜单的所有菜单项都是根路由的children,<router-view>路由视图占位符,渲染映射组件路由的亲儿子children里面的路由规则中所映射的组件。
为啥要main-layout.vue这个组件,因为路由视图占位符<router-view>路由视图占位符只负责渲染当前组件路由亲儿子children下的路由所映射的组件。但我们有多层嵌套,所以需要一个公共的组件来渲染多层嵌套的路由所映射的组件。为啥不用layout/index.vue,因为它里面渲染的是整个页面的结构,包括侧边栏、头部、主要内容区域,用layout/index.vue的话页面会项俄罗斯套娃。
App.vue中的<router-view>用来渲染根路由所映射的组件。
layout/index.vue中的<router-view>用来渲染根路由的亲儿子级别的路由映射的组件。
main-layout.vue中的<router-view>用来渲染各模块下面的children的路由映射的组件
路由列表结构
三级菜单
路由部分,meeting.js:
/** 引入公共组件 */
import { MainLayout } from '../constant'
/**
* @description 会议室路由
*/
export default {
path: '/meeting-manage' /** 路径 */,
name: 'meeting-manage' /** 名称 */,
component: MainLayout /** 组件 */,
meta: {
/** 路由元信息 */
title: '会议室管理' /** 菜单的名称 */,
icon: 'el-icon-pie-chart' /** 菜单的图标 */,
role: 500 /** 页面权限 */,
rank: 4 /** 排序,数值越大越靠后(下) */
},
children: [
// 多层嵌套菜单
{
path: 'nest',
name: 'nest',
component: MainLayout,
meta: {
title: '第二层'
},
children: [
{
path: 'nest3-1',
name: 'nest3-1',
component: () => import(/* webpackChunkName: "meeting-manage" */ '@/views/meeting-room/nest.vue'),
meta: {
title: '第三层-1'
}
},
{
path: 'nest3-2',
name: 'nest3-2',
component: () => import(/* webpackChunkName: "meeting-manage" */ '@/views/meeting-room/fore.vue'),
meta: {
title: '第三层-2'
}
}
]
}
]
}
四级菜单路由结构
/** 引入公共组件 */
import { MainLayout } from '../constant'
/**
* @description 会议室路由
*/
export default {
path: '/meeting-manage' /** 路径 */,
name: 'meeting-manage' /** 名称 */,
component: MainLayout /** 组件 */,
meta: {
/** 路由元信息 */
title: '会议室管理' /** 菜单的名称 */,
icon: 'el-icon-pie-chart' /** 菜单的图标 */,
role: 500 /** 页面权限 */,
rank: 4 /** 排序,数值越大越靠后(下) */
},
children: [
// 多层嵌套菜单
{
path: 'nest',
name: 'nest',
component: MainLayout,
meta: {
title: '第二层'
},
children: [
{
path: 'nest3-1',
name: 'nest3-1',
component: () => import(/* webpackChunkName: "meeting-manage" */ '@/views/meeting-room/nest.vue'),
meta: {
title: '第三层-1'
},
children: [
{
path: 'nest4',
name: 'nest4',
component: () => import(/* webpackChunkName: "meeting-manage" */ '@/views/meeting-room/fore.vue'),
meta: {
title: '第四层菜单'
}
}
]
}
]
}
]
}
侧边栏组件结构
侧边栏内菜单项组件部分 sidebar-item.vue
在这个组件中使用到了组件递归,这个组件的结构是:一级菜单和下拉菜单,下拉菜单里面又会有一级菜单和下拉菜单以此类推,那么下拉菜单的结构跟这个组件的结构完全一模一样,所以才下拉菜单中使用组件自己,进行组件递归。
<template>
<div>
<!-- 仅一级菜单 -->
<el-menu-item v-if="!(item.children && item.children.length !== 0)"
:index="item.path">
<i :class="item.meta.icon"></i>
<span slot="title">{{ item.meta.title }}</span>
</el-menu-item>
<!-- 多级菜单 -->
<el-submenu v-else
:index="item.path">
<template>
<template slot="title">
<i :class="item.meta.icon"></i>
<span slot="title">{{ item.meta.title }}</span>
</template>
</template>
<!-- 组件自己使用自己,递归组件 -->
<sidebar-item v-for="child in item.children"
:key="child.path"
:item="child" />
</el-submenu>
</div>
</template>
<script>
export default {
name: 'SidebarItem',
props: {
// 菜单项
item: {
type: Object,
required: true
}
}
}
</script>
<style lang="scss" scoped></style>
侧边栏组件部分 sidebar/index.vue
<template>
<div class="sidebar">
<!-- logo -->
<Logo />
<!-- 侧边栏菜单 -->
<el-menu :default-active="$route.name"
background-color="#001529"
text-color="#9fa3a8"
active-text-color="#fff"
class="el-menu-vertical-demo"
@open="handleOpen"
@close="handleClose"
@select="handleSelect"
:collapse="isCollapse">
<sidebar-item v-for="item in userRoutes[0].children"
:key="item.name"
:item="item" />
</el-menu>
</div>
</template>