文章目录
- 主体布局搭建
- 左侧菜单搭建
- 左侧菜单跳转
主体布局搭建
我们在 Container 布局容器,找到有左侧、头部、和主体部分的布局,直接复制代码到 Main.vue 中:
<template>
<div>
<el-container>
<el-aside width="200px">Aside</el-aside>
<el-container>
<el-header>Header</el-header>
<el-main><router-view></router-view></el-main>
</el-container>
</el-container>
</div>
</template>
左侧菜单搭建
在导航菜单中找到我们需要的直接复制示例代码到项目中即可
我们在 components 中新建 CommonAside.vue ,做为左侧菜单的组件,把复制的代码放进去
<template>
<div class="hello">
<el-menu
default-active="2"
class="el-menu-vertical-demo"
@open="handleOpen"
@close="handleClose"
background-color="#545c64"
text-color="#fff"
active-text-color="#ffd04b">
<el-submenu index="1">
<template slot="title">
<i class="el-icon-location"></i>
<span>导航一</span>
</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<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">
<template slot="title">选项4</template>
<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>
</div>
</template>
<script>
export default {
data() {
return {
isCollapse: true
};
},
methods: {
handleOpen(key, keyPath) {
console.log(key, keyPath);
},
handleClose(key, keyPath) {
console.log(key, keyPath);
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.el-menu-vertical-demo:not(.el-menu--collapse) {
width: 200px;
min-height: 400px;
}
</style>
然后在 Main.vue 中引入组件
<template>
<div>
<el-container>
<el-aside width="200px">
<CommonAside />
</el-aside>
<el-container>
<el-header>Header</el-header>
<el-main><router-view></router-view></el-main>
</el-container>
</el-container>
</div>
</template>
<script>
import CommonAside from "@/components/CommonAside";
export default {
name: "Main",
components:{
CommonAside
}
}
</script>
<style scoped>
</style>
运行项目现在的样式:
我们修改默认代码,使用 for 循环动态渲染成我们所需要的导航数据:
<template>
<div class="hello">
<el-menu
default-active="2"
class="el-menu-vertical-demo"
@open="handleOpen"
@close="handleClose"
background-color="#545c64"
text-color="#fff"
active-text-color="#ffd04b">
<el-menu-item v-for="item in noChildren" :key="item.name" :index="item.name">
<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.name" :index="item.name">
<template slot="title">
<i :class="`el-icon-${item.icon}`"></i>
<span>{{item.label}}</span>
</template>
<el-menu-item-group v-for="subItem in item.children" :key="subItem.name">
<el-menu-item :index="subItem.name">{{subItem.label}}</el-menu-item>
</el-menu-item-group>
</el-submenu>
</el-menu>
</div>
</template>
<script>
export default {
data() {
return {
isCollapse: true,
menuData: [
{
path: '/',
name: 'home',
label: '首页',
icon: 's-home',
url: 'Home/home'
},
{
path: '/mall',
name: 'mall',
label: '商品管理',
icon: 'video-play',
url: 'MallManage/MallManager'
},
{
path: '/user',
name: 'user',
label: '用户管理',
icon: 'user',
url: 'UserManage/UserManager'
},
{
label: '其他',
icon: 'location',
name: 'other',
children:[
{
path: '/page1',
name: 'page1',
label: '页面1',
icon: 'setting',
url: 'Other/PageOne'
},
{
path: '/page2',
name: 'page2',
label: '页面2',
icon: 'setting',
url: 'Other/PageTwo'
}
]
},
]
};
},
methods: {
handleOpen(key, keyPath) {
console.log(key, keyPath);
},
handleClose(key, keyPath) {
console.log(key, keyPath);
}
},
computed:{
// 没有子菜单
noChildren(){
return this.menuData.filter(item => !item.children)
},
// 有子菜单
hasChildren(){
return this.menuData.filter(item => item.children)
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.el-menu-vertical-demo:not(.el-menu--collapse) {
width: 200px;
min-height: 400px;
}
</style>
运行程序:
对代码进行分析:我们使用计算属性分为有子菜单和没有子菜单的两部分,然后分别遍历
我们用到了图标:Icon,使用方法就是在 <i>
中使用对应 class 即可,我们观察到图标的前边都是一样的,所以我们使用 ES6的模板语法,只改变后边的名称即可
由于我们需要修改左侧菜单的样式,我们可以使用 less(less官方文档),我们需要先下载安装执行npm i less@4.1.2
还需要安装npm i less-loader@6.0.0
之后修改 CommonAside.vue 中代码,增加一个标题,然后修改样式如下:
<template>
<div class="hello">
<el-menu
default-active="2"
class="el-menu-vertical-demo"
@open="handleOpen"
@close="handleClose"
background-color="#545c64"
text-color="#fff"
active-text-color="#ffd04b">
<h3>通用后台管理</h3>
......
</el-menu>
</div>
</template>
<script>
......
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style lang="less" scoped>
.el-menu-vertical-demo:not(.el-menu--collapse) {
width: 200px;
min-height: 400px;
}
.el-menu{
height: 100vh;
h3{
color: #fff;
text-align: center;
line-height: 48px;
font-size: 16px;
font-weight: 400;
}
}
</style>
现在样式是这样的,左边有默认的边距,所以需要修改 App.vue 去掉边距
<template>
<div id="app">
<!-- 路由出口 -->
<!-- 路由匹配到的组件将渲染在这里 -->
<router-view></router-view>
</div>
</template>
<script>
</script>
<style lang="less">
html,body,h3{
margin: 0;
padding: 0;
}
</style>
运行效果如下:
左侧菜单跳转
在 CommonAside 中我们的菜单数据中已经有了跳转路径,我们需要加到 index.js 中
这里的 path 就复制 CommonAside 中对应菜单的 path 即可
import Vue from 'vue'
......
//1、创建组件
import Home from '../views/Home';
import User from '../views/User';
import Main from '../views/Main';
import Mall from '../views/Mall';
import PageOne from '../views/PageOne';
import PageTwo from '../views/PageTwo';
//2、将路由与组件进行映射
const routes = [
{
//主路由
path: '/',
component: Main,
children: [
{ path: 'home', component: Home },// 主页
{ path: 'user', component: User },// 用户管理
{ path: 'mall', component: Mall },// 商品管理
{ path: 'page1', component: PageOne },// 页面1
{ path: 'page2', component: PageTwo },// 页面2
]
}
]
//3、创建router实例
......
这样当我们在浏览器地址栏修改地址时,页面就会展示对应的页面了
下面完成点击左侧菜单进行跳转,所以需要给菜单添加 click 事件,传入点击的菜单的数据,使用 router 进行跳转
<template>
<div class="hello">
<el-menu
default-active="2"
class="el-menu-vertical-demo"
@open="handleOpen"
@close="handleClose"
background-color="#545c64"
text-color="#fff"
active-text-color="#ffd04b">
<h3>通用后台管理</h3>
<el-menu-item v-for="item in noChildren" :key="item.name" :index="item.name" @click="menuClick(item)">
<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.name" :index="item.name">
<template slot="title">
<i :class="`el-icon-${item.icon}`"></i>
<span>{{item.label}}</span>
</template>
<el-menu-item-group v-for="subItem in item.children" :key="subItem.name">
<el-menu-item :index="subItem.name">{{subItem.label}}</el-menu-item>
</el-menu-item-group>
</el-submenu>
</el-menu>
</div>
</template>
<script>
export default {
......
methods: {
......
menuClick(item) {
this.$router.push(item.path)
}
},
......
}
</script>
index.js 中需要增加redirect:'/home'
,这样当以为首页的路径是 /
,当点击时需要重定向到 home 页面
const routes = [
{
//主路由
path: '/',
component: Main,
redirect:'/home',
children: [
{ path: 'home', component: Home },// 主页
{ path: 'user', component: User },// 用户管理
{ path: 'mall', component: Mall },// 商品管理
{ path: 'page1', component: PageOne },// 页面1
{ path: 'page2', component: PageTwo },// 页面2
]
}
]
然后我们解决一个问题,当我们已经点击了商品管理时,当再次点击一次商品管理时会报错,这是因为 router 限制了我们不能重复跳转,如果重复跳转就会有这个提示
所以我们需要在跳转时进行判断,如果需要跳转的路径和当前路径相同就不进行跳转
menuClick(item) {
// 当页面的路由与跳转的路由不一致才进行跳转
if(this.$route.path !== item.path && !(this.$route.path === '/home' && item.path === '/')){
this.$router.push(item.path)
}
}