HM后台(二)

一,home组件,侧边栏静态页面搭建,

1.1。去element-ui找组件

按需引入element组件

import Vue from 'vue'
import {
  Button,
  Form,
  FormItem,
  Input,
  Message,
  Container,
  Header,
  Aside,
  Main,
  Menu,
  Submenu,
  MenuItemGroup,
  MenuItem
} from 'element-ui'

Vue.prototype.$message = Message
Vue.use(Button)
Vue.use(Form)
<template>
  <el-container>
    <!-- 头部 -->
    <el-header>
      <div>
        <img src="../assets/heima.png" alt="" />
        <span>电商管理后台</span>
      </div>
      <el-button type="primary" size="default" @click="logout">退出</el-button>
    </el-header>
    <!-- 页面主体区域 -->
    <el-container>
      <!-- 侧边栏 -->
      <el-aside width="200px">
        <!-- 侧边栏菜单区域 -->
        <el-menu
          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 index="1-4-1">
              <!-- 二级菜单模板 -->
              <template slot="title">
                <i class="el-icon-location"></i>
                <span>导航二</span>
              </template>
            </el-menu-item>
          </el-submenu>
        </el-menu>
      </el-aside>
      <!-- 右侧主体区域 -->
      <el-main>Main</el-main>
    </el-container>
  </el-container>
</template>

样式

在element-ui中,组件名称就是类名,比如 .el-button

<style lang="less" scoped>
.el-container {
  height: 100%;
}

.el-header {
  background-color: #373d41;
  // 开始弹性盒子
  display: flex;
  // 主轴对齐
  justify-content: space-between;
  // 副轴对齐方式
  align-items: center;
  color: #fff;
  font-size: 20px;
  // 左边padding为0
  padding-left: 0;
  & div {
    display: flex;
    align-items: center;
    span {
      margin-left: 20px;
    }
  }
}

.el-aside {
  background-color: #333744;
}

.el-main {
  background-color: #eaedf1;
}
</style>

二,配置请求拦截器,添加token

在main.js中配置

import axios from 'axios'
// 配置请求的跟路径
axios.defaults.baseURL = 'http://127.0.0.1:8888/api/private/v1/'
Vue.prototype.$http = axios
// 配置请求拦截器,添加token
axios.interceptors.request.use(config => {
  // console.log(config)
  config.headers.Authorization = window.sessionStorage.getItem('token')
  return config
})

三,发送请求,获取左菜单栏的数据

 // 获取侧边栏菜单的数据
    async getMenuList() {
      const { data: res } = await this.$http.get('menus')
      console.log(res)
      if (res.meta.status === 200) {
        this.$message.success(res.meta.msg)
        this.menuList = res.data
      } else {
        this.$message.error('获取数据失败')
      }
    }
四,数据填充模板
4.1,注,index,是字符窜

   <!-- 侧边栏菜单区域 -->
        <el-menu
          background-color="#545c64"
          text-color="#fff"
          active-text-color="#ffd04b"
        >
          <!-- 一级菜单 -->
          <el-submenu :index="item.id+''"  v-for="(item, index) 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, index) in item.children" :key="subitem.id">
              <!-- 二级菜单模板 -->
              <template slot="title">
                <!-- 图标 -->
                <i class="el-icon-location"></i>
                <!-- 文本 -->
                <span>{{subitem.authName}}</span>
              </template>
            </el-menu-item>
          </el-submenu>
        </el-menu>

五,菜单栏的图标设置,以及颜色设置

5.1,点击菜单栏时,颜色变化

 <!-- 侧边栏菜单区域 -->
        <el-menu
          background-color="#545c64"
          text-color="#fff"
          active-text-color="#409EFF"
        >

5.2,二级菜单栏的图标设置,用element-ui的图标组件

<!-- 二级菜单 -->
            <el-menu-item :index="`${subitem.id}`" v-for="(subitem, index) in item.children" :key="subitem.id">
              <!-- 二级菜单模板 -->
              <template slot="title">
                <!-- 图标 -->
                <i class="el-icon-menu"></i>

5.3,一级菜单图标设置,需要设置成不同的图标,一级菜单的类名是写死了,如何变活呢

方法;一级菜单已经v-for循环了,但是他们有唯一的id值,我们可以利用id和图标类名组成键值对,组成一个对象,就可动态显示图标类名了。用阿里巴巴图标

 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-submenu
            :index="item.id + ''"
            v-for="(item, index) in menuList"
            :key="item.id"
          >
            <!-- 一级菜单模板 -->
            <template slot="title">
              <!-- 图标 -->
              <i :class="iconsObj[item.id]"></i>

图标设置padding距离

.iconfont{
  padding-right: 10px;
}

六,点击一个一级菜单,上一个展开的一级菜单自动关闭

在el-menu添加一个属性,只写属性,默认是true

  <!-- 侧边栏菜单区域 -->
        <el-menu
          background-color="#545c64"
          text-color="#fff"
          active-text-color="#409EFF"
          unique-opened
        >

6.1,点击二级菜单,右边有一些边框突出,需要在el-menu设置边框为0

 

.el-aside {
  background-color: #333744;
  .el-menu{
    border-right: 0;
  }
}

七,左侧菜单的折叠与展开功能

   

7.1,我们先在el-menu添加一个div结构,用于点击时,左侧菜单栏的折叠与展开,el-menu组件中有两个属性,我们默认设置不折叠,点击新增的div结构时,collapse取反,取消动画,

而且el-aside的宽度也要动态设置

 

 <el-aside :width="isCollapse ? '64px': '200px'">
        <div class="toggle-button" @click="toggleCollapse">|||</div>
        <!-- 侧边栏菜单区域 -->
        <el-menu
          background-color="#545c64"
          text-color="#fff"
          active-text-color="#409EFF"
          unique-opened
          :collapse="isCollapse"
          :collapse-transition="false"
        >
data() {
    return {
      isCollapse: false,
.el-aside {
  background-color: #333744;
  .toggle-button {
    background-color: #4a5064;
    font-size: 10px;
    height: 24px;
    line-height: 24px;
    color: #fff;
    // 文本水平居中
    text-align: center;
    // 字间距
    letter-spacing: 0.2em;
    // 小手状态
    cursor: pointer;
  }
// 点击左侧菜单栏的折叠与展开
    toggleCollapse() {
      this.isCollapse = !this.isCollapse
    }

八,实现home组件路由重定向

8.1,在view中新增welcome子路由组件,在路由文件中配置

 {
    path: '/home',
    component: Home,
    // 重定向
    redirect: '/welcome',
    children: [{ path: '/welcome', component: Welcome }]
  }
  <!-- 右侧主体区域 -->
      <el-main>
        <!-- 路由占位符 -->
        <router-view></router-view>
        </el-main>

九,左侧二级菜单改成路由连接,el-menu开启路由模式,点击后会跳转

 请求回来的菜单栏数据中,有个path属性,我们将二级菜单的index的属性值设置为它,前边加个‘/’,此时就是路由的路径

c

  <!-- 侧边栏菜单区域 -->
        <el-menu
          background-color="#545c64"
          text-color="#fff"
          active-text-color="#409EFF"
          unique-opened
          :collapse="isCollapse"
          :collapse-transition="false"
          router
        >
 <!-- 二级菜单 -->
            <el-menu-item
              :index="'/' + subitem.path"
              v-for="(subitem, index) in item.children"
              :key="subitem.id"
            >

十,用户列表开发

10.1,点击二级菜单的用户列表,跳转到user组件,在views新增user组件,是home的子路由,在路由文件中配置路由对象

import User from '@/views/User'
{
    path: '/home',
    component: Home,
    // 重定向
    redirect: '/welcome',
    children: [
      { path: '/welcome', component: Welcome },
      { path: '/users', component: User }
    ]
  }

此时有个小bug,点击二级菜单,文本没有高亮

 

 我们需要激活它,每次点击二级菜单的路由连接时,我们需要将他的路劲赋值给这个属性。

home组件创建时,需要激活,点击二级菜单也要激活

   <!-- 二级菜单 -->
            <el-menu-item
              :index="'/' + subitem.path"
              v-for="(subitem, index) in item.children"
              :key="subitem.id"
              @click="saveNavState('/' + subitem.path)"
            >
 saveNavState(activePath) {
      window.sessionStorage.setItem('activePath', activePath)
      this.activePath = activePath
    }
 mounted() {
    this.getMenuList()
    this.activePath = window.sessionStorage.getItem('activePath')
  },
data() {
    return {
      isCollapse: false,
      menuList: [],
      // 被激活的链接地址
      activePath: '',
    <!-- 侧边栏菜单区域 -->
        <el-menu
          background-color="#545c64"
          text-color="#fff"
          active-text-color="#409EFF"
          unique-opened
          :collapse="isCollapse"
          :collapse-transition="false"
          router
          :default-active="activePath"
        >

10.2,user路由组件,面包屑搭建

 <!-- 面包屑导航区域 -->
    <el-breadcrumb separator-class="el-icon-arrow-right">
      <el-breadcrumb-item to="/home">首页</el-breadcrumb-item>
      <el-breadcrumb-item>用户管理</el-breadcrumb-item>
      <el-breadcrumb-item>用户列表</el-breadcrumb-item>
    </el-breadcrumb>

样式

.el-breadcrumb {
  margin-bottom: 20px;
  margin-bottom: 15px;
  font-size: 12px;
}

.el-card {
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15) !important;
}

10.3,卡片视图搭建

input框和button按钮的宽度比例,使用栅格layout,:span为每列的宽度, :gutter为列与列的距离

   <!-- 卡片视图 -->
    <el-card>
      <!-- 栅格 -->
      <el-row :gutter="20">
        <el-col :span="8">
          <el-input placeholder="请输入内容">
            <el-button slot="append" icon="el-icon-search"></el-button>
          </el-input>
        </el-col>

        <el-col :span="4">
          <el-button type="primary" size="default">添加</el-button>
        </el-col>
      </el-row>
    </el-card>

10.4,发送请求,获取用户数据

data() {
    return {
      // 获取用户列表的参数对象
      queryInfo: {
        query: '',
        // 当前的页数
        pagenum: 1,
        // 当前每页显示多少条数据
        pagesize: 2
      },
      userlist: [],
      total: 0
    }

get请求,

 axios.get(url, {配置})  // {params: {id: 1}}, 是问号的参数,相当于query参数
axios({
      url: '路径', // 这个路径中可以包含params或query参数
      method: 'get/post/put/delete',
      params: {}, // 包含query参数的对象,问号后面的参数
      data: {}, // 包含请求体参数的对象
    })
 
 mounted() {
    this.getUserList()
  },

  methods: {
    // 发送请求,获取用户列表数据
    async getUserList() {
      const { data: res } = await this.$http.get('users', {
        params: this.queryInfo
      })
      console.log(res)
      if (res.meta.status === 200) {
        this.userlist = res.data.users
        this.total = res.data.total
      } else {
        this.$message.error('获取用户数据失败')
      }
    }
  }

返回的数据

10.5,用户列表静态页面搭建

el-switch选择开关组件v-modle收集的是布尔值,决定开或者闭合

<!-- 用户列表区域 -->
      <el-table :data="userlist" border stripe style="margin:20px 0">
        <el-table-column type="index"></el-table-column>
        <el-table-column label="姓名" prop="username"></el-table-column>
        <el-table-column label="邮箱" prop="email"></el-table-column>
        <el-table-column label="电话" prop="mobile"></el-table-column>
        <el-table-column label="角色" prop="role_name"></el-table-column>
        <el-table-column label="状态">
          <template slot-scope="{ row, $index }">
            <el-switch
              v-model="row.mg_state"
              active-color="#13ce66"
              inactive-color="#ff4949"
            >
            </el-switch>
          </template>
        </el-table-column>
        <el-table-column label="操作" width="180px"> </el-table-column>
      </el-table>

10.6,操作栏静态页面搭建

注;tooltip文字提示组件,

  <el-table-column label="操作" width="180px">
          <template slot-scope="{row , $index}">
            <!-- 修改按钮 -->
            <el-button type="primary" icon="el-icon-edit" size="mini" title="编辑"></el-button>
            <!-- 删除按钮 -->
            <el-button type="danger" icon="el-icon-delete" size="mini" title="删除"></el-button>
            <!-- 分配角色按钮 -->
            <el-tooltip effect="dark" content="分配角色" placement="top" :enterable="false">
              <el-button type="warning" icon="el-icon-setting" size="mini"></el-button>
            </el-tooltip>
          </template>
        </el-table-column>

10.7,分页组件搭建

   <!-- 分页区域 -->
      <el-pagination @size-change="handleSizeChange" @current-change="getUserList" 
        :current-page="queryInfo.pagenum" :page-sizes="[1, 2, 5, 10]" 
        :page-size="queryInfo.pagesize" layout=" prev, pager, next, jumper,->,->, sizes,total" :total="total">
      </el-pagination>
 // 每页多少条数据
    handleSizeChange(size) {
      this.queryInfo.pagesize = size
      // 重新发送请求,获取最新数据
      this.getUserList()
    }
// 发送请求,获取用户列表数据
    async getUserList(page = 1) {
      this.queryInfo.pagenum = page
      const { data: res } = await this.$http.get('users', {
        params: this.queryInfo
      })
      console.log(res)
      if (res.meta.status === 200) {
        this.userlist = res.data.users
        this.total = res.data.total
      } else {
        this.$message.error('获取用户数据失败')
      }
    },

 10.8,实现用户状态修改功能

 更改的状态,需要重新发送请求,同步到数据库中

  <el-table-column label="状态">
          <template slot-scope="{ row, $index }">
            <el-switch
              v-model="row.mg_state"
              active-color="#13ce66"
              inactive-color="#ff4949"
              @change="userStateChanged(row)"
            >
            </el-switch>
          </template>
        </el-table-column>
   // 监听 switch 开关状态的改变
    async userStateChanged(userinfo) {
      //点击状态开关, 此时mg_state属性已经修改了,需要发送请求,同步更改到数据库
      console.log(userinfo)
      const { data: res } = await this.$http.put(
        `users/${userinfo.id}/state/${userinfo.mg_state}`
      )
      if (res.meta.status !== 200) {
        userinfo.mg_state = !userinfo.mg_state
        return this.$message.error('更新用户状态失败!')
      }
      this.$message.success('更新用户状态成功!')
    }
 
原文地址:https://www.cnblogs.com/fsg6/p/14264912.html