一、配置嵌套路由【功能实现】
1、打开vue-router官方文档,查找嵌套路由部分
针对页面不变的部分,定义为外层路由,对于改变的部分,在children中定义为子路由
官方示例代码如下:
const router = new VueRouter({
routes: [
{
path: '/user/:id',
component: User,
children: [
{
// 当 /user/:id/profile 匹配成功,
// UserProfile 会被渲染在 User 的 <router-view> 中
path: 'profile',
component: UserProfile
},
{
// 当 /user/:id/posts 匹配成功
// UserPosts 会被渲染在 User 的 <router-view> 中
path: 'posts',
component: UserPosts
}
]
}
]
})
2、创建主路由:在views文件夹下创建Main.vue
在router文件夹下的index.js配置主路由
①创建主路由文件
②将原路由改写为嵌套路由【注意,子路由不可带/】
此时,App.vue的路由出口指的是主路由,因此还需在主路由Main.vue文件中提供子路由的路由出口【因为子路由会显示在主路由的内部】,打开Main.vue配置路由出口
3、此时访问页面,如下图所示说明嵌套路由配置完成
二、基于UI设计导航栏布局【样式美观】
1、根据UI图,到element官网查找对应的container布局容器
本项目的UI样式基于左侧导航栏、顶栏和中间内容main实现,官方代码如下:
<el-container>
<el-aside width="200px">Aside</el-aside>
<el-container>
<el-header>Header</el-header>
<el-main>Main</el-main>
</el-container>
</el-container>
将上述代码写入Main.vue主路由文件中,原先子路由出口写入<el-main>中
2、在src文件夹下的components文件夹中注册左侧导航栏组件CommonAside.vue,到element官网中选择样式,并根据官网文档封装属性进行修改,本项目选用的原生样式如下图所示:
官网原代码如下:
<el-menu default-active="1-4-1" class="el-menu-vertical-demo" @open="handleOpen" @close="handleClose" :collapse="isCollapse">
<el-submenu index="1">
<template slot="title">
<i class="el-icon-location"></i>
<span slot="title">导航一</span>
</template>
<el-menu-item-group>
<span slot="title">分组一</span>
<el-menu-item index="1-1">选项1</el-menu-item>
<el-menu-item index="1-2">选项2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="1-3">选项3</el-menu-item>
</el-menu-item-group>
<el-submenu index="1-4">
<span slot="title">选项4</span>
<el-menu-item index="1-4-1">选项1</el-menu-item>
</el-submenu>
</el-submenu>
<el-menu-item index="2">
<i class="el-icon-menu"></i>
<span slot="title">导航二</span>
</el-menu-item>
<el-menu-item index="3" disabled>
<i class="el-icon-document"></i>
<span slot="title">导航三</span>
</el-menu-item>
<el-menu-item index="4">
<i class="el-icon-setting"></i>
<span slot="title">导航四</span>
</el-menu-item>
</el-menu>
将上述代码改写进入CommonAside.vue文件中,主要注意一级菜单和二级菜单写法(后续会有改写后的具体代码展示)
3、在主路由文件Main.vue中引入左侧导航栏,实现CommonAside.vue组件的引入、注册和使用
4、针对一级菜单和二级菜单的写法提供详细说明:
4.1 在script中的data部分写入一级菜单和二级菜单的数据,为后续数据渲染提供数据基础,定义数组menuData用于存放导航栏数据
①一级菜单数据写法
//一级菜单写法
{
path: '/teachingmanage',
name: 'teachingmanage',
label: '教研管理',
icon: 's-home',
url: 'TeachingManage/TeachingManage'
},
②二级菜单数据写法
//二级菜单写法
{
label: '研修管理',
icon: 's-home',
children: [
{
path: '/coursecenter',
name: 'coursecenter',
label: '课程中心',
icon: 's-home',
url: 'StudyManage/CourseCenter'
},
{
path: '/questionbank',
name: 'questionbank',
label: '题库管理',
icon: 's-home',
url: 'StudyManage/QuestionBank'
},
]
},
4.2 在script中的comupted部分定义判断有子菜单和无菜单的方法,为后续页面渲染数据奠定基础
①没有子菜单,判断item的children不存在,并将结果return
noChildren() {
return this.menuData.filter(item => !item.children)
},
②有子菜单,与没有子菜单的判断取反即可
hasChildren() {
return this.menuData.filter(item => item.children)
}
4.3 在页面上渲染数据,实现导航栏数据的显示
①一级菜单页面渲染数据代码:
<!-- 一级菜单 -->
<!-- index用于确定选中的菜单项,是唯一标识 -->
<!-- v-bind:(简写为:,用于属性绑定) -->
<el-menu-item @click="clickMenu(item)" v-for="item in noChildren" :key="item.name" :index="item.name">
<!-- `el-icon-${item.icon}`与data中的数据绑定,实现动态拼接 -->
<i :class="`el-icon-${item.icon}`"></i>
<span slot="title">{{ item.label }}</span>
</el-menu-item>
②二级菜单页面渲染数据代码:
<!-- 二级菜单 -->
<el-submenu v-for=" item in hasChildren" :key="item.label" index="item.label">
<!-- slot表示插槽 -->
<template slot="title">
<i :class="`el-icon-${item.icon}`"></i>
<span slot="title">{{ item.label }}</span>
</template>
<!-- 对子菜单进行渲染 -->
<el-menu-item-group v-for="subItem in item.children" :key="subItem.path">
<el-menu-item @click="clickMenu(subItem)" :index="subItem.path">{{ subItem.label }}</el-menu-item>
</el-menu-item-group>
</el-submenu>
4.4 CommonAside.vue文件的完整代码如下:
<template>
<div>
<el-menu default-active="1-4-1" class="el-menu-vertical-demo" @open="handleOpen" @close="handleClose"
:collapse="isCollapse">
<!-- 一级菜单 -->
<!-- index用于确定选中的菜单项,是唯一标识 -->
<!-- v-bind:(简写为:,用于属性绑定) -->
<el-menu-item @click="clickMenu(item)" v-for="item in noChildren" :key="item.name" :index="item.name">
<!-- `el-icon-${item.icon}`与data中的数据绑定,实现动态拼接 -->
<i :class="`el-icon-${item.icon}`"></i>
<span slot="title">{{ item.label }}</span>
</el-menu-item>
<!-- 二级菜单 -->
<el-submenu v-for=" item in hasChildren" :key="item.label" index="item.label">
<!-- slot表示插槽 -->
<template slot="title">
<i :class="`el-icon-${item.icon}`"></i>
<span slot="title">{{ item.label }}</span>
</template>
<!-- 对子菜单进行渲染 -->
<el-menu-item-group v-for="subItem in item.children" :key="subItem.path">
<el-menu-item @click="clickMenu(subItem)" :index="subItem.path">{{ subItem.label }}</el-menu-item>
</el-menu-item-group>
</el-submenu>
</el-menu>
</div>
</template>
<script>
export default {
data() {
return {
//控制导航栏为展开模式
isCollapse: false,
//存放导航栏数据
menuData: [
//一级菜单写法
{
path: '/teachingmanage',
name: 'teachingmanage',
label: '教研管理',
icon: 's-home',
url: 'TeachingManage/TeachingManage'
},
{
path: '/scientificmanage',
name: 'scientificmanage',
label: '科研管理',
icon: 's-home',
url: 'ScientificManage/ScientificManage'
},
//二级菜单写法
{
label: '研修管理',
icon: 's-home',
children: [
{
path: '/coursecenter',
name: 'coursecenter',
label: '课程中心',
icon: 's-home',
url: 'StudyManage/CourseCenter'
},
{
path: '/questionbank',
name: 'questionbank',
label: '题库管理',
icon: 's-home',
url: 'StudyManage/QuestionBank'
},
{
path: '/examinationpaper',
name: 'examinationpaper',
label: '试卷管理',
icon: 's-home',
url: 'StudyManage/ExaminationPaperManage'
},
{
path: '/trainingmanage',
name: 'trainingmanage',
label: '培训管理',
icon: 's-home',
url: 'StudyManage/TrainingManage'
},
]
},
//一级菜单写法
{
path: '/evalutionmanage',
name: 'evalutionmanage',
label: '评价管理',
icon: 's-home',
url: 'EvalutionManage/EvalutionManage'
},
{
path: '/supervisioncenter',
name: 'supervisioncenter',
label: '监管中心',
icon: 's-home',
url: 'SupervisionCenter/SupervisionCenter'
},
{
path: '/usermanage',
name: 'usermanage',
label: '用户管理',
icon: 's-home',
url: 'UserManage/UserManage'
},
]
}
},
methods: {
handleOpen() {
},
handleClose() {
}
},
computed: {
//没有子菜单,判断item的children不存在,并将结果return
noChildren() {
return this.menuData.filter(item => !item.children)
},
//有子菜单,与没有子菜单的判断取反即可
hasChildren() {
return this.menuData.filter(item => item.children)
}
}
}
</script>
运行项目,打开页面,发现导航栏菜单数据渲染成功【注意,为了说明el-main中的内容,下图展示时在url地址栏键入了home】
在下一节将介绍对导航栏样式的具体修改