<template>
<el-container>
<!-- 头部 -->
<el-header>
<div class="left">
<img src="../assets/imgs/shop.png" alt="">
<span>后台管理系统</span>
</div>
<div class="right">
<span>欢迎您:{{userInfo.username}}</span>
<el-button type="danger" size="mini" @click="logout">退出</el-button>
</div>
</el-header>
<el-container>
<!-- 侧边栏 -->
<el-aside width="200px">
<!--侧边菜单-->
<el-menu
default-active="2"
class="el-menu-vertical-demo"
>
<el-submenu index="1">
<template slot="title">
<i class="el-icon-location"></i>
<span>导航一</span>
</template>
<el-menu-item index="1-4-1">选项1</el-menu-item>
<el-menu-item index="1-4-1">选项2</el-menu-item>
<el-menu-item index="1-4-1">选项3</el-menu-item>
</el-submenu>
</el-menu>
</el-aside>
<!-- 主题区域 -->
<el-main>Main</el-main>
</el-container>
</el-container>
</template>
<script>
export default {
data(){
return{
userInfo:null,
menuList:[]
}
},
created(){
// 获取用户信息 用以展示到首页
this.userInfo = JSON.parse(sessionStorage.getItem('userInfo'))
this.getMenuList()
},
methods:{
// 退出
logout(){
this.$confirm('确定要退出登录吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
// 点击确定后 清除session用户信息
sessionStorage.clear()
// 跳转到登录页面
this.$router.push('/login')
}).catch(() => {
// this.$message({
// type: 'info',
// message: '已取消退出'
// });
});
},
// 获取左侧的菜单列表
// 使用async await 修饰
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
}
}
}
</script>
<style lang='less' scope>
.el-container{
height: 100%;
}
.el-header{
background: url('../assets/imgs/header_bg.gif') repeat-x center;
height: 50px!important;
display: flex;
justify-content: space-between;
align-items: center;
color: white;
.left{
display: flex; //显示在同一行
align-items: center; // 垂直对齐
img{
width: 40px;
margin-right: 20px; // 图片和文字的距离
}
span{
font-size: 20px;
}
}
.right{
margin-left: 10px;
}
}
</style>
会提示无效的token,因为除了登录页面其他请求都需要携带token,否则会认为是没有权限
在main.js中为请求头添加token
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import './plugins/element.js'
// 导入全局样式表
import './assets/imgs/css/global.css'
//导入字体图标
import './assets/fonts/iconfont.css'
// 引入axios
import axios from 'axios'
Vue.prototype.$http = axios
// 配置axios基础路径
axios.defaults.baseURL = 'http://www.tangxiaoyang.vip:8888/api/v2'
// 拦截所有请求,为请求头添加token认证(拦截器)
axios.interceptors.request.use(config => {
// 获取用户信息
const userInfo = JSON.parse(sessionStorage.getItem('userInfo'))
// 向请求头中添加token
config.headers.Authorization = userInfo ? userInfo.token : ''
return config
})
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App)
}).$mount('#app')
在退出再登录的时候会报错显示获取不到token,因为登录的时候就会验证token,那时候还没把token添加到session中所以获取不到,这里做个判断
config.headers.Authorization = userInfo ? userInfo.token : ''
<!--侧边菜单-->
<el-menu
default-active="2"
class="el-menu-vertical-demo"
>
<el-submenu :index="item.id+''" v-for="item in menuList" :key='item.id'>
<template slot="title">
<i class="el-icon-location"></i>
<span>{{item.authName}}</span>
</template>
<el-menu-item :index="subItem.id+''" v-for="subItem in item.children" :key="subItem.id">
<i class="el-icon-menu"></i>
{{subItem.authName}}
</el-menu-item>
</el-submenu>
</el-menu>
每个一级菜单前面的图标都是一样的,但是实际上应该是不一样的
data(){
return{
//用户信息
userInfo:null,
// 左侧菜单列表
menuList:[],
// 图标样式对象
iconObj:{
'201':'iconfont icon-shouye',
'125':'iconfont icon-users',
'103':'iconfont icon-tijikongjian',
'101':'iconfont icon-shangpin',
'102':'iconfont icon-danju',
}
}
},
<!--侧边菜单-->
<el-menu
default-active="2"
class="el-menu-vertical-demo"
>
<el-submenu :index="item.id+''" v-for="item in menuList" :key='item.id'>
<template slot="title">
<i :class="iconObj[item.id]"></i>
<span>{{item.authName}}</span>
</template>
<el-menu-item :index="subItem.id+''" v-for="subItem in item.children" :key="subItem.id">
<i class="el-icon-menu"></i>
{{subItem.authName}}
</el-menu-item>
</el-submenu>
</el-menu>
左侧导航栏优化
默认同时可打开多个菜单,限制设置为同一时间只能打开一个
unique-opened
<el-menu
default-active="2"
unique-opened
>
<el-submenu :index="item.id+''" v-for="item in menuList" :key='item.id'>
<template slot="title">
<i :class="iconObj[item.id]"></i>
<span>{{item.authName}}</span>
</template>
<el-menu-item :index="subItem.id+''" v-for="subItem in item.children" :key="subItem.id">
<i class="el-icon-menu"></i>
{{subItem.authName}}
</el-menu-item>
</el-submenu>
</el-menu>
添加router属性 就有了路由跳转的功能
是否使用 vue-router 的模式,启用该模式会在激活导航时以 index 作为 path 进行路由跳转
登录后跳转到首页home,现在需要点击首页中的欢迎页,把内容展示到home主体部分
index.js中配置路由
在home下的children中配置,这里是把欢迎页的内容展示在home页主体部分,所以需要在
const routes = [
// 访问根路径的时候跳转到login
{
path: '/',
redirect: '/login'
},
{
path: '/login',
component: Login
},
{
path: '/home',
component: () =>
import ('../components/Home.vue'),
children: [{
path: '/welcome',
component: () =>
import ('../components/index/Welcome.vue')
}]
}
]
home.vue
<!-- 主题区域 -->
<el-main>
<router-view></router-view>
</el-main>
这里默认是登录后跳转到home页,这里可以重定向到欢迎页
index.js
{
path: '/home',
component: () =>
import ('../components/Home.vue'),
redirect: '/welcome',
children: [{
path: '/welcome',
component: () =>
import ('../components/index/Welcome.vue')
}]
}
设置默认选择欢迎页,高亮
<!--侧边菜单-->
<el-menu
:default-active="$route.path"
unique-opened
router
>
<el-submenu :index="item.id+''" v-for="item in menuList" :key='item.id'>
<template slot="title">
<i :class="iconObj[item.id]"></i>
<span>{{item.authName}}</span>
</template>
<!--这里的index是要跳转的地址 -->
<el-menu-item :index="'/'+ subItem.path" v-for="subItem in item.children" :key="subItem.id">
<i class="el-icon-menu"></i>
{{subItem.authName}}
</el-menu-item>
</el-submenu>
</el-menu>
<!-- 侧边栏 -->
<!-- 这个宽度设置成动态的 没折叠是200,折叠的话设置小一点 -->
<el-aside :width="isCollapse ? '64px' : '200px' ">
<!--菜单的折叠和显示-->
<!-- isCollapse 菜单是否折叠 -->
<div class="toggle-button" @click="isCollapse=!isCollapse">|||</div>
<!--侧边菜单-->
<el-menu
:default-active="$route.path"
unique-opened
router
:collapse='isCollapse'
:collapse-transition="false"
>
<el-submenu :index="item.id+''" v-for="item in menuList" :key='item.id'>
<template slot="title">
<i :class="iconObj[item.id]"></i>
<span>{{item.authName}}</span>
</template>
<!--这里的index是要跳转的地址 -->
<el-menu-item :index="'/'+ subItem.path" v-for="subItem in item.children" :key="subItem.id">
<i class="el-icon-menu"></i>
{{subItem.authName}}
</el-menu-item>
</el-submenu>
</el-menu>
</el-aside>
data(){
return{
//用户信息
userInfo:null,
// 左侧菜单列表
menuList:[],
// 图标样式对象
iconObj:{
'201':'iconfont icon-shouye',
'125':'iconfont icon-users',
'103':'iconfont icon-tijikongjian',
'101':'iconfont icon-shangpin',
'102':'iconfont icon-danju',
},
// 是否折叠左侧菜单
isCollapse:false
}
},
完整代码
<template>
<el-container>
<!-- 头部 -->
<el-header>
<div class="left">
<img src="../assets/imgs/shop.png" alt="">
<span>后台管理系统</span>
</div>
<div class="right">
<span>欢迎您:{{userInfo.username}}</span>
<el-button type="danger" size="mini" @click="logout">退出</el-button>
</div>
</el-header>
<el-container>
<!-- 侧边栏 -->
<!-- 这个宽度设置成动态的 没折叠是200,折叠的话设置小一点 -->
<el-aside :width="isCollapse ? '64px' : '200px' ">
<!--菜单的折叠和显示-->
<!-- isCollapse 菜单是否折叠 -->
<div class="toggle-button" @click="isCollapse=!isCollapse">|||</div>
<!--侧边菜单-->
<el-menu
:default-active="$route.path"
unique-opened
router
:collapse='isCollapse'
:collapse-transition="false"
>
<el-submenu :index="item.id+''" v-for="item in menuList" :key='item.id'>
<template slot="title">
<i :class="iconObj[item.id]"></i>
<span>{{item.authName}}</span>
</template>
<!--这里的index是要跳转的地址 -->
<el-menu-item :index="'/'+ subItem.path" v-for="subItem in item.children" :key="subItem.id">
<i class="el-icon-menu"></i>
{{subItem.authName}}
</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{
//用户信息
userInfo:null,
// 左侧菜单列表
menuList:[],
// 图标样式对象
iconObj:{
'201':'iconfont icon-shouye',
'125':'iconfont icon-users',
'103':'iconfont icon-tijikongjian',
'101':'iconfont icon-shangpin',
'102':'iconfont icon-danju',
},
// 是否折叠左侧菜单
isCollapse:false
}
},
created(){
// 获取用户信息 用以展示到首页
this.userInfo = JSON.parse(sessionStorage.getItem('userInfo'))
this.getMenuList()
},
methods:{
// 退出
logout(){
this.$confirm('确定要退出登录吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
// 点击确定后 清除session用户信息
sessionStorage.clear()
// 跳转到登录页面
this.$router.push('/login')
}).catch(() => {
// this.$message({
// type: 'info',
// message: '已取消退出'
// });
});
},
// 获取左侧的菜单列表
// 使用async await 修饰
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(this.menuList)
}
}
}
</script>
<style lang='less' scope>
.el-container{
height: 100%;
}
.el-header{
background: url('../assets/imgs/header_bg.gif') repeat-x center;
height: 50px!important;
display: flex;
justify-content: space-between;
align-items: center;
color: white;
.left{
display: flex; //显示在同一行
align-items: center; // 垂直对齐
img{
width: 40px;
margin-right: 20px; // 图片和文字的距离
}
span{
font-size: 20px;
}
}
.right{
margin-left: 10px;
}
}
.el-aside{
.el-menu{
border-right: 0; //不需要有边框
.iconfont{
margin-right: 10px;
}
}
.toggle-button{
background: #60779d;
font-size: 10px;
line-height: 24px;
text-align: center;
color: white;
letter-spacing: 0.2rem; //字符间距
cursor: pointer; //鼠标移上去是手的样式
}
}
.el-main{
background: #eaedf1;
}
</style>