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>

 

posted on 2021-04-27 18:00  KannoRi  阅读(288)  评论(0)    收藏  举报