Vue学习笔记-03-电商系统主页
1.实现主页的布局
实现主页的布局,首先我们可以去element-ui上去找有没有现成的布局代码,我们找到组件下的Container选项下有左右布局直接copy过来
<el-container>
<el-header>Header</el-header>
<el-container>
<el-aside width="200px">Aside</el-aside>
<el-main>Main</el-main>
</el-container>
</el-container>
不要忘记在element.js内注册el-container组件
将布局copy过来,查看页面的布局。然后我们发现主页的布局没有展开到全屏,按F12打开开发者模式查看代码,发现el-container没有占面100%,我们给外侧的el-contianer赋予一个class="home-container"然后在<style>中给home-container设定css样式: height: 100%;即可让整个container撑满整个屏幕。
然后我们给整理好的布局添加背景色,这里会用到吸色工具获取喜欢的颜色的十六进制代码。在Vue中,element-ui布局内的el-header el-container都是默认的class,可以直接获取用类名选择器选中,el-container也可以直接获取,只不过我们为了防止有更多的container出现所以给el-container取了一个名字。'.'是选择类'>'是选择标签,和css选择器的用法一致。同时支持{}嵌套。为整个布局都更改各自的颜色后,我们增添导航栏的具体布局。
首先头顶有一个logo,旁边是“电商管理系统”的标题,最右边是退出按钮,用于logout。那我们用弹性布局最为方便,给el-header一个display:flex属性,使用justify-content和align-items属性让显示好看。在header里新建一个div用来规定布局,加入一个logo<img>,src来定位图片的资源。
2.导航菜单栏的布局
我们去element-ui寻找侧边栏菜单的布局copy下来。
<el-col :span="12">
<h5>自定义颜色</h5>
<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>
</el-col>
在这个基础上,我们梳理一下,el-menu是整个菜单的父容器,然后el-submenu是第一个菜单点击项,el-menu-item是多级菜单。我们实现的菜单是从后端发来的响应数据中拿到的权限,根据权限中显示的菜单项来动态渲染菜单,因此我们只需要默认留一个一级菜单其中包含二级菜单即可。<template>是模板项,保存的是el-menu的模板,例如<i>是icon,<span>是文本。我们把整个菜单要放置在侧边栏<el-aside>里面去,让整个menu右对齐,设置好背景色。
3.利用向请求的header中加入token来访问后端的Authorization请求(后端可以用@RequesrtHeader来实现检查Header中的属性)
axios的请求拦截器是前端的一个验证,我们把token放到Authorization字段中,传回后端,后端就可以获取token校验本token和颁发给用户的token是否是一个token来实现安全验证。我们在main.js中定义一个请求拦截器,用回调函数给每个请求加上Authorization字段。
axios.interceptors.request.use(config => {
config.headers.Authorization = window.sessionStorage.getItem('token')
return config
})
这样每个请求的Header都会带上Authorization字段,而且字段的值都带有token验证。
为Home.vue设置生命周期created()函数,调用this.getmenuList(),在data()中定义menuList数组,menuList:[],使用async await在getmenuList函数内向后端服务器发送请求,获取menu菜单的数据。
// 获取所有的菜单
async getMenuList() { //async 异步获取 await 同步函数 这个搭配是vue中常用的申请请求方式
const { data: res } = await this.$http.get('menus') //await函数是等待发送请求获取的数据
if(res.meta.status !== 200) return this.$message.error(res.meta.msg);
this.menulist = res.data
// 获取了侧边栏的数据
console.log(this.menulist)
}
4.利用获取的数据动态渲染菜单
我们获取的menuList在控制台打印出来大体是这个样子的:
(5) [{…}, {…}, {…}, {…}, {…}, __ob__: Observer]0: authName: (...)children: (...)id: (...)order: (...)path: (...)__ob__: Observerdep: Dep {id: 79, subs: Array(1)}value: {…}vmCount: 0__proto__: Objectget authName: ƒ reactiveGetter()set authName: ƒ reactiveSetter(newVal)get children: ƒ reactiveGetter()set children: ƒ reactiveSetter(newVal)get id: ƒ reactiveGetter()set id: ƒ reactiveSetter(newVal)get order: ƒ reactiveGetter()set order: ƒ reactiveSetter(newVal)get path: ƒ reactiveGetter()set path: ƒ reactiveSetter(newVal)__proto__: Object1: {…}2: {…}3: {…}4: {…}length: 5__ob__: Observer {value: Array(5), dep: Dep, vmCount: 0}__proto__: Array
我们利用两层循环的方式将authName读出来,用id作为key值,再读children即可。在Vue中用v-for的方式设置view的循环来动态渲染。
<!-- 侧边栏 -->
<el-aside :width="isCollapse ? '64px': ' 200px'" >
<div class="toggle-button" @click = "toggleCollapse">|||</div>
<!-- 菜单区域 -->
<el-menu background-color="#333744" text-color="#fff"
active-text-color="#4098FF" :unique-opened="true" :collapse="isCollapse"
:collapse-transition="false" :router="true">
<!-- 一级菜单 -->
<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 :index="'/'+subItem.path" v-for="subItem in item.children" :key="subItem.id">
<template slot="title">
<!-- 图标 -->
<i class="el-icon-menu"></i>
<!-- 文本 -->
<span>{{subItem.authName}}</span>
</template>
</el-menu-item>
</el-submenu>
</el-menu>
</el-aside>
每个父菜单的图标都不同,我们可以从后端获取数据来实现,或者我们可以根据id单独定义一个map表来获取图标,此处的图标要支持动态绑定,用':'来进行动态绑定,':'是'v-bind'的语法糖。
在data()下定义iconsObj这个对象
iconsObj: {
'125':'el-icon-user-solid',
'103':'el-icon-s-tools',
'101':'el-icon-s-goods',
'102':'el-icon-s-order',
'145':'el-icon-s-marketing'
}
这里的每个icon都是element-ui提供的icon。
5.设置侧边栏菜单缩放
element-ui支持自带的侧边栏缩放,el-menu自带一个属性名称为collapse,默认为false,当其为true的时候菜单栏就折叠。我们定义一个按钮,赋予其一个方法toggleCollapse,在data()中设置一个bool值isCollapsed,toggleCollapse方法将isCollapsed取非即可。然后我们要将el-aside的大小和菜单栏一起做调整。
<el-aside :width="isCollapse ? '64px': ' 200px'" >
用lambda表达式来完成。
最终,利用unique-opened="true"规定其只能同时打开一个侧边栏,collapse-transition="false"关闭打开关闭动画,然后利用router属性实现index的名称请求。侧边栏就完成啦。
6.页面路由重定向
新建一个Welcome.vue,在Home.vue的el-main中设置路由占位符<router-view>,然后我们在/home下设置子路由children:,下面设定path:/welcome,这样显示的component就是在Home.vue内显示的了。利用redirect来实现路由重定向,Welcome要import进来。
{ path: '/home',
redirect: '/welcome',
component: Home,
children:[{ path: '/welcome', component: Welcome }]
}
整个Home.vue页面的代码如下:
<template>
<el-container class="home-container">
<!-- 头部区 -->
<el-header>
<div>
<img src="../assets/mainmenu.svg">
<span>电商后台管理系统</span>
</div>
<el-button type="info" @click="logout">退出</el-button>
</el-header>
<!-- 页面主体区 -->
<el-container>
<!-- 侧边栏 -->
<el-aside :width="isCollapse ? '64px': ' 200px'" >
<div class="toggle-button" @click = "toggleCollapse">|||</div>
<!-- 菜单区域 -->
<el-menu background-color="#333744" text-color="#fff"
active-text-color="#4098FF" :unique-opened="true" :collapse="isCollapse"
:collapse-transition="false" :router="true">
<!-- 一级菜单 -->
<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 :index="'/'+subItem.path" v-for="subItem in item.children" :key="subItem.id">
<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':'el-icon-user-solid',
'103':'el-icon-s-tools',
'101':'el-icon-s-goods',
'102':'el-icon-s-order',
'145':'el-icon-s-marketing'
},
// 是否折叠
isCollapse: false
}
},
// 生命周期函数
created() {
this.getMenuList()
},
methods:{
logout(){
window.sessionStorage.clear();
this.$router.push("/login");
},
// 获取所有的菜单
async getMenuList() { //async 异步获取 await 同步函数 这个搭配是vue中常用的申请请求方式
const { data: res } = await this.$http.get('menus') //await函数是等待发送请求获取的数据
if(res.meta.status !== 200) return this.$message.error(res.meta.msg);
this.menulist = res.data
// 获取了侧边栏的数据
console.log(this.menulist)
},
// 点击按钮切换菜单的折叠与展开
toggleCollapse(){
this.isCollapse=! this.isCollapse
}
}
};
</script>
<style lang="less" scoped>
.home-container{
height: 100%;
}
.el-header{
background-color: #373D41;
display: flex;
justify-content: space-between;//flex布局 空间在中间
align-items: center;//按钮居中
color: #fff;
font-size: 20px;
>div{//规定el-header里的div布局
display: flex;
align-items: center;
img{
height: 50px;
}
span{
margin-left: 15px;
}
}
}
.el-aside{
background-color: #333744;
.el-menu{
border-right: 0;
}
}
.el-main{
background-color: #eaedf1;
}
.toggle-button{
background-color: #4A5064;
font-size: 10px; //字体大小
line-height: 24px;//行高
color: #fff;
text-align: center; //居中显示文本
letter-spacing: 0.2em; //字体间隔
cursor: pointer; //鼠标放置上显示小手
}
</style>
浙公网安备 33010602011771号