主页布局
先上下划分,再左右划分
组件库中找到 “Container布局容器”
<el-container class="home_container">
<!-- 头部区域 -->
<el-header></el-header>
<el-container>
<!-- 侧边栏区域 -->
<el-aside></el-aside>
<!-- 右侧主体区域 -->
<el-main></el-main>
</el-container>
</el-container>
注意:el-container这类标签本身都相当于类选择器
需要找到容器没有撑满全屏的原因
<style>
.home_container {
height:100%;
}
</style>
实现左右布局最简单的方法就是使用:flex布局
<!-- 头部区域 -->
<el-header>
<div>
<img src="../assets/heima.png" alt="" />
<span>电商后台管理系统</span>
</div>
<el-button type="info" @click="logout">退出</el-button>
</el-header>
<style lang="less" scoped>
.el-header {
background-color: #373d41;
display: flex;
justify-content: space-between;
padding-left: 0;
align-items: center;
color: #fff;
font-size: 22px;
> div {
display: flex;
align-items: center;
span {
padding-left: 15px;
}
}
</style>
在组件库中找到“ NavMenu 导航菜单“——为网站提供导航功能的菜单
菜单分为两级,并且可以折叠
<el-menu
background-color="#333744"
text-color="#fff"
active-text-color="#ffd04b"
>
<!-- 一级菜单 -->
<el-submenu index="1">
<!-- 一级菜单模板区域 -->
<template slot="title">
<!-- 图标 -->
<i class="el-icon-s-custom"></i>
<!-- 文本 -->
<span>用户管理</span>
</template>
<!-- 二级菜单 -->
<el-menu-item>
<i class="el-icon-user"></i>
<span>用户列表</span>
</el-menu-item>
</el-submenu>
</el-menu>
- 有el-submenu就得记得加template slot="title"模板,不管里面有没有二级菜单,三级菜单,都会有绿框中的”小箭头“
- 而二级菜单el-menu-item可以不添加template模板,那就变成了单独的一个菜单项,不会有子菜单了,没有“小箭头”,比如角色列表,权限列表以及一级菜单:商品管理
需要授权的API,必须在请求头中使用 Authorization
字段提供 token 令牌
后台除了登录接口之外,都需要token权限验证,我们可以通过添加axios请求拦截器来添加token,以保证拥有获取数据的权限,
在main.js中添加代码,然后将axios挂载到vue原型之前添加下面的代码
//请求在到达服务器之前,先会调用use中的这个回调函数来添加请求头信息
axios.interceptors.request.use(config=>{
//为请求头对象,添加token验证的Authorization字段
config.headers.Authorization = window.sessionStorage.getItem("token")
return config
})
随后打开Network,退出重新登录一次,会发现请求头Request Headers 中出现了 Authorization: null
在页面刚加载的时候就应该立即获取左侧菜单栏数据,所以我们可以定义一个生命周期函数 created() 并调用 getMenuList() 来获取左侧菜单,拿到数据后,为了能在页面中渲染出来,应该把获取到的数据立即挂载到data中,然后再根据status值进行判断
<script>
export default {
name: 'Home',
data() {
return {
// 第三步:左侧菜单数据
menulist: []
}
},
// 第一步:在created阶段请求左侧菜单数据
created() {
this.getMenuList()
},
methods: {
logout() {
// 1.清除 token
window.sessionStorage.clear()
// 重定向到登录页
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)
}
}
}
</script>
在这之前,我犯了个低级错误,根据老师的菜单栏内容,在模板中把他们都一个个敲出来了,实际步骤其实应该是先获取到左侧菜单栏 的数据,然后直接 v-for 渲染就行
// 渲染一级菜单
<el-submenu index="1" v-for="item in menulist" :key="item.id">
// 这时,展开一项其他项也展开,那就需要设置唯一的index
<el-submenu :index="item.id" v-for="item in menulist" :key="item.id">
// 结果却报错了,是因为 index 只接受字符串,不接受数值,两种方法:
<el-submenu :index="item.id + ''" v-for="item in menulist" :key="item.id">
<el-submenu :index="String(item.id)" v-for="item in menulist" :key="item.id">
// 渲染二级菜单,是建立在一级菜单的基础之上,主要区别就在于 subitem in item.children
<el-menu-item :index="subitem.id + ''" v-for="subitem in item.children" :key="subitem.id">
<!-- 一级菜单 -->
<el-submenu
:index="item.id + ''"
v-for="item in menulist"
:key="item.id"
>
<!-- 一级菜单模板区域 -->
<template slot="title">
<!-- 图标 -->
<i class="el-icon-s-custom"></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-user"></i>
<span>{{ subItem.authName }}</span>
</el-menu-item>
</el-submenu>
最后效果:
通过更改el-menu的active-text-color属性可以设置侧边栏菜单中点击的激活项的文字颜色
active-text-color="#409EFF"
修改二级菜单的图标
<i class="el-icon-menu"></i>
修改一级菜单图标,因为每个都不一样,所以需要使用第三方的字体图标库
main.js中引入字体图标
// 导入字体图标
import './assets/fonts/iconfont.css'
通过更改菜单项模板(template)中的i标签的类名,可以将左侧菜单栏的图标进行设置,我们需要在项目中使用第三方字体图标,在数据中添加一个iconsObj,id作为key,图标为value,然后将图标类名进行数据绑定,绑定iconsObj中的数据,即:在class前加冒号,动态获取图标,最后设置一下图标与文本之间的间距,但是这个方法有点鸡肋?吧
<!-- 图标 -->
<i :class="iconsObj[item.id]"></i>
data() {
return {
// 第三步:左侧菜单数据
menulist: [],
iconsObj: {
125: 'iconfont icon-user',
103: 'iconfont icon-tijikongjian',
101: 'iconfont icon-shangpin',
102: 'iconfont icon-danju',
145: 'iconfont icon-baobiao'
}
}
},
为了保持左侧菜单每次只能打开一个,显示其中的子菜单,我们可以在el-menu中添加一个属性unique-opened;
或者也可以数据绑定进行设置(此时true认为是一个bool值,而不是字符串) :unique-opened=“true”
unique-opened
:是否只保持一个子菜单的展开,默认值是false
<el-menu background-color="#333744" text-color="#fff" active-text-color="#409EFF" unique-opened>
</el-menu>
// 或者是写成 :unique-opened="true"
// 记得加上冒号,虽然不加冒号也有效果,但是控制台会报错
我们会发现展开的菜单右边框会有点突出去,这是怎么回事呢?
// 原因:
.el-menu {
border-right: solid 1px #e6e6e6;
}
// 解决办法:
.el-aside {
background-color: #333744;
.el-menu {
border-right: none;
}
}
添加能够实现伸缩功能的按键
<div class="toggle-button" @click="toggleCollapse">|||</div>
绑定点击事件 toggleCollapse
:collapse
:是否水平折叠收起菜单(仅在 mode 为 vertical 时可用),默认值为 false
:collapse-transition
:是否开启折叠动画,默认值为 true
// 在 el-menu 中数据绑定进行设置
:collapse="isCollapse"
:collapse-transition="false" // 关闭折叠动画效果
data() {
isCollapse:false
},
methods: {
// 点击按钮,切换菜单的折叠与展开
toggleCollapse() {
this.isCollapse = !this.isCollapse
}
}
实现伸缩功能后,希望菜单栏宽度能随之变化
不要把菜单栏宽度写成固定值,而是可以利用三元运算符,width的值根据 isCollapse 进行动态切换
<el-aside :width="isCollapse ? '64px' : '200px'">
新增子级路由组件Welcome.vue
在router/index.js
中导入子级路由组件,并设置路由规则以及子级路由的默认重定向
打开Home.vue
,在main的主体结构中添加一个路由占位符
import Welcome from '../components/Welcome.vue' // 导入Welcome组件
const router = new VueRouter({
routes: [
{
path: '/',
redirect: '/login'
},
{
path: '/login',
component: Login
},
{
path: '/home',
component: Home,
redirect: '/welcome',
children: [
{
path: '/welcome',
component: Welcome
}
]
}
]
})
// Home.vue
<!-- 右侧内容主体区域 -->
<el-main>
<!-- 路由占位符 -->
<router-view></router-view>
</el-main>
制作好了Welcome子级路由之后,我们需要将所有的侧边栏二级菜单都改造成子级路由链接
我们只需要将 el-menu 的 router 属性设置为true就可以了,此时当我们点击二级菜单的时候,就会根据菜单的index属性进行路由跳转,如: /110
router
:是否使用 vue-router 的模式,启用该模式会在激活导航时以 index 作为 path 进行路由跳转,默认值是false
使用index id来作为跳转的路径不合适,我们可以重新绑定index的值为 :index=" '/' + subItem.path"
<!-- 二级菜单 -->
<el-menu-item :index="'/' + subItem.path" v-for="subItem in item.children" :key="subItem.id">
…未完待续