整体布局:先上下划分,再左右划分。
<el-container>
<!-- 头部区域 -->
<el-header></el-header>
<el-container>
<!-- 侧边栏区域 -->
<el-aside></el-aside>
<!-- 右侧主体区域 -->
<el-main></el-main>
</el-container>
</el-container>
菜单分为二级,并且可以折叠。
<el-menu>
<el-submenu>
<!-- 这个 template 是一级菜单的内容模板 -->
<i class="el-icon-menu"></i>
<span>一级菜单</span>
<!-- 在一级菜单中,可以嵌套二级菜单 -->
<el-menu-item>
<i class="el-icon-menu"></i>
<span slot="title">二级菜单</span>
</el-menu-item>
</el-submenu>
</el-menu>
通过axios请求拦截器添加token,保证拥有获取数据的权限
// 通过axios请求拦截器添加token,保证拥有获取数据的权限
// axios请求拦截
// 在 request 拦截器中,展示进度条 NProgress.start()
axios.interceptors.request.use(config => {
// 显示进度条
NProgress.start();
// 为请求头对象,添加token 验证的Authorization字段
config.headers.Authorization = window.sessionStorage.getItem('token');
return config;
});
通过 v-for 双层循环分别进行一级菜单和二级菜单的渲染
通过路由相关属性启用菜单的路由功能
data() {
return {
// 左侧菜单数据
menulist: [],
// 一级菜单图标对象
iconsObj: {
'125': 'iconfont icon-user',
'103': 'iconfont icon-tijikongjian',
'101': 'iconfont icon-shangpin',
'102': 'iconfont icon-danju',
'145': 'iconfont icon-baobiao'
},
// 菜单栏是否折叠
isCollapse: false,
// 被激活的链接地址
activePath: ''
}
}
created() {
// 获取所有的菜单
this.getMenuList();
// 菜单选中状态链接地址
this.activePath = window.sessionStorage.getItem('activePath');
}
methods: {
// 退出登录
logout() {
// 1、先清除 sessionStorage中的token
window.sessionStorage.clear()
// 2、再跳转到 登录页面
this.$router.push('/login')
},
// 获取所有的菜单
async getMenuList() {
const {data: res} = await this.$http.get('menus');
if(res.meta.status !== 200) return this.$message.error(res.meta.msg);
this.menulist = res.data;
// console.log(res);
},
// 点击按钮,切换菜单的折叠与展开
toggleCollapse() {
this.isCollapse = !this.isCollapse;
},
// 保存链接的激活状态(菜单的选中状态)
saveNavState(activePath) {
window.sessionStorage.setItem('activePath', activePath);
this.activePath = activePath;
}
}
}
<!-- 侧边栏菜单区域 -->
<!-- active-text-color 选中后的文本颜色 -->
<!-- unique-opened 是否只保持一个子菜单的展开 布尔值 -->
<!-- collapse 是否水平折叠收起菜单 -->
<!-- collapse-transition 是否开启折叠动画 -->
<!-- router 是否使用 vue-router 的模式,启用该模式会在激活导航时以 index 作为 path 进行路由跳转 -->
<!-- default-active 当前激活菜单的 index, 菜单的选中状态 -->
<el-menu background-color="#333744" text-color="#fff" active-text-color="#409BFF" unique-opened :collapse='isCollapse' :collapse-transition='false' router :default-active='activePath'>
<!-- 一级菜单 el-submenu-->
<!-- index 控制选项卡,展开、折叠,是字符串类型 -->
<el-submenu :index="item.id + '' " v-for="item in menulist" :key="item.id">
<!-- 一级菜单模板区域 -->
<template slot="title">
<!-- 图标 -->
<i :class="iconsObj[item.id]"></i>
<!-- 文本 -->
<span>{{item.authName}}</span>
</template>
<!-- 二级菜单区域 el-menu-item-->
<!-- router,开启路由模式后,二级菜单通过 index进行页面的跳转 -->
<el-menu-item :index="'/' + subItem.path " v-for="subItem in item.children" :key="subItem.id" @click="saveNavState('/' + subItem.path)">
<!-- 二级菜单模板区域 -->
<template slot="title">
<!-- 图标 -->
<i class="el-icon-menu"></i>
<!-- 文本 -->
<span>{{subItem.authName}}</span>
</template>
</el-menu-item>
</el-submenu>
</el-menu>
</el-aside>
完整代码
<template>
<el-container class="home-container">
<!-- 头部区域 -->
<el-header>
<div>
<img src="../assets/heima.png" alt="">
<span>电商后台管理系统</span>
</div>
<el-button type="info" @click="logout">退出</el-button>
</el-header>
<!-- 主体区域 -->
<el-container>
<!-- 侧边栏 -->
<!-- 根据 collapse 是否水平折叠收起菜单,来决定 侧边栏的宽度 -->
<el-aside :width="isCollapse ? '64px' : '200px'">
<!-- 菜单栏折叠按钮 -->
<div class="toggle-button" @click="toggleCollapse">|||</div>
<!-- 侧边栏菜单区域 -->
<!-- active-text-color 选中后的文本颜色 -->
<!-- unique-opened 是否只保持一个子菜单的展开 布尔值 -->
<!-- collapse 是否水平折叠收起菜单 -->
<!-- collapse-transition 是否开启折叠动画 -->
<!-- router 是否使用 vue-router 的模式,启用该模式会在激活导航时以 index 作为 path 进行路由跳转 -->
<!-- default-active 当前激活菜单的 index, 菜单的选中状态 -->
<el-menu background-color="#333744" text-color="#fff" active-text-color="#409BFF" unique-opened :collapse='isCollapse' :collapse-transition='false' router :default-active='activePath'>
<!-- 一级菜单 el-submenu-->
<!-- index 控制选项卡,展开、折叠,是字符串类型 -->
<el-submenu :index="item.id + '' " v-for="item in menulist" :key="item.id">
<!-- 一级菜单模板区域 -->
<template slot="title">
<!-- 图标 -->
<i :class="iconsObj[item.id]"></i>
<!-- 文本 -->
<span>{{item.authName}}</span>
</template>
<!-- 二级菜单区域 el-menu-item-->
<!-- router,开启路由模式后,二级菜单通过 index进行页面的跳转 -->
<el-menu-item :index="'/' + subItem.path " v-for="subItem in item.children" :key="subItem.id" @click="saveNavState('/' + subItem.path)">
<!-- 二级菜单模板区域 -->
<template slot="title">
<!-- 图标 -->
<i class="el-icon-menu"></i>
<!-- 文本 -->
<span>{{subItem.authName}}</span>
</template>
</el-menu-item>
</el-submenu>
</el-menu>
</el-aside>
<!-- 主体内容区域 -->
<el-main>
<!-- 路由占位符 -->
<router-view></router-view>
</el-main>
</el-container>
</el-container>
</template>
<script>
export default {
data() {
return {
// 左侧菜单数据
menulist: [],
// 一级菜单图标对象
iconsObj: {
'125': 'iconfont icon-user',
'103': 'iconfont icon-tijikongjian',
'101': 'iconfont icon-shangpin',
'102': 'iconfont icon-danju',
'145': 'iconfont icon-baobiao'
},
// 菜单栏是否折叠
isCollapse: false,
// 被激活的链接地址
activePath: ''
}
},
created() {
// 获取所有的菜单
this.getMenuList();
// 菜单选中状态链接地址
this.activePath = window.sessionStorage.getItem('activePath');
},
methods: {
// 退出登录
logout() {
// 1、先清除 sessionStorage中的token
window.sessionStorage.clear()
// 2、再跳转到 登录页面
this.$router.push('/login')
},
// 获取所有的菜单
async getMenuList() {
const {data: res} = await this.$http.get('menus');
if(res.meta.status !== 200) return this.$message.error(res.meta.msg);
this.menulist = res.data;
// console.log(res);
},
// 点击按钮,切换菜单的折叠与展开
toggleCollapse() {
this.isCollapse = !this.isCollapse;
},
// 保存链接的激活状态(菜单的选中状态)
saveNavState(activePath) {
window.sessionStorage.setItem('activePath', activePath);
this.activePath = activePath;
}
}
}
</script>
<style lang="less" scoped>
// 整个大盒子
.home-container {
height: 100%;
}
// 头部区域
.el-header {
display: flex;
// 设置主轴上的子元素排列方式
// space-between 先两边贴边,再平分剩余空间
justify-content: space-between;
background-color: #373d41;
padding-left: 0;
// 设置侧轴上的子元素排列方式(单行 )
align-items: center;
color: #fff;
font-size: 20px;
div {
display: flex;
align-items: center;
span {
margin-left: 15px;
}
}
}
// 侧边栏区域
.el-aside {
background-color: #333744;
// 菜单栏折叠按钮
.toggle-button {
background-color: #4a5064;
color: #fff;
font-size: 10px;
line-height: 24px;
text-align: center;
// 字符间距
letter-spacing: 0.2em;
cursor: pointer;
}
// 去除 选中项 右边的 1px 灰色边框
.el-menu{
border-right: none;
}
// 一级菜单中 icon图标 与 文字 之间的距离
.iconfont {
margin-right: 10px;
}
}
// 主体区域
.el-main {
background-color: #eaedf1;
}
</style>