【Vue】實戰專案:電商後臺管理系統(Element-UI)(一)前後端搭建 - 登入介面 - 主頁介面

2021-04-09 07:00:14

文章目錄


專案地址https://gitee.com/ykang2020/vue_shop

0. 專案介紹

電商管理系統(Element-UI)

電商後臺管理系統用於管理使用者賬號、商品分類、商品資訊、訂單、資料統計等業務功能
在這裡插入圖片描述

開發模式

電商後臺管理系統整體採用前後端分離的開發模式,其中前端專案是基於 Vue 技術棧的 SPA(單頁應用程式) 專案
在這裡插入圖片描述

前端技術棧

  • Vue
  • Vue-router
  • Element-UI
  • Axios
  • Echarts

後端技術棧

  • Node.js
  • Express
  • Jwt(模擬session)
  • Mysql
  • Sequelize(運算元據庫的框架)

1. 設定——初始化 前端專案

① 安裝 Vue 腳手架

② 通過 Vue 腳手架建立專案

③ 設定 Vue 路由

④ 設定 Element-UI 元件庫

⑤ 設定 axios 庫

⑥ 語法處理ESLint

⑦ 初始化 git 遠端倉庫

⑧ 將本地專案託管到 Github 或 碼雲 中

詳見【Vue】vue-cli - 圖形化建立專案 - 設定專案 - axios - elementUI - 碼雲SSH公鑰設定 - Gitee同步

2. 設定後端介面

① 安裝 MySQL 資料庫

  1. 使用phpStudy軟體(關閉Apache)
    在這裡插入圖片描述
  2. 匯入資料庫檔案(路徑不能有中文)
    在這裡插入圖片描述
  3. 檢查資料 裡面有資料說明匯入完成
    在這裡插入圖片描述

② 安裝 Node.js 環境

③ 設定專案相關資訊

cd E:\YKcode\web\myProject01\api\vue_api_server
cnpm install

④ 啟動專案

出錯了就多 npm installcnpm install 幾下

node app.js

在這裡插入圖片描述

⑤檢視API檔案電商管理後臺 API 介面檔案.md

![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210314154316727.png?x-oss-process=image/waterma在這裡插入圖片描述

⑥ 使用 Postman 測試後臺專案介面是否正常

在這裡插入圖片描述
根據檔案測試
在這裡插入圖片描述
偵錯成功
在這裡插入圖片描述

3. 登入/退出功能

3.1 登入業務流程

① 在登入頁面輸入使用者名稱和密碼
② 呼叫後臺介面進行驗證
③ 通過驗證之後,根據後臺的響應狀態跳轉到專案主頁

3.2 登入業務的相關技術點

  • http 是無狀態的 (stateless)(不儲存通訊狀態)
  • 通過 cookie 在使用者端記錄狀態 (前端與後端沒有跨域問題使用)
  • 通過 session 在伺服器端記錄狀態 (前端與後端沒有跨域問題使用)
  • 通過 token 方式維持狀態 (有跨域問題時使用)

相關參考【徹底理解cookie,session,token - 墨顏丶 - 部落格園】

3.3 token原理

在這裡插入圖片描述

3.4 登入功能實現

3.4.1 佈局分析

在這裡插入圖片描述
通過 Element-UI 元件實現佈局

  • el-form
  • el-form-item
  • el-input
  • el-button
  • 字型圖示

3.4.2 Git 建立login分支

建立分支

git checkout -b login

檢視分支

git branch

在這裡插入圖片描述

3.4.3 渲染Login元件並實現路由重定向

  1. 清空Vue模板和路由 main.js App.vue ./components/HelloWorld.vue ./views
  2. 建立元件 ./view/Login.vue
  3. 新增路由規則 ./router/index.js 設定預設頁面重定向到login
import Login from '../components/Login.vue'
const routes = [
  { path: '/', redirect: '/login' },
  { path: '/login', component: Login }
]
  1. 新增路由預留位置 App.vue
  <div id="app">
    <!-- 路由預留位置 -->
    <router-view></router-view>
  </div>

3.4.4 設定背景顏色並在螢幕中央繪製登入盒子

  1. 在視覺化工具中安裝 開發依賴 less 和 less-loader
  2. 安裝過依賴後要重新編譯
  3. 設定全域性樣式 ./assets/css/global.css
/* 全域性樣式表 */
html,
body,
#app {
  height: 100%;
  margin: 0;
  padding: 0;
  min-width: 1366px;
}
  1. 入口檔案匯入全域性css檔案 ./main.js
// 匯入全域性樣式表
import './assets/css/global.css'
  1. 設定背景顏色並在螢幕中央繪製登入盒子 Login.vue
<div class="login_container">
  <div class="login_box"></div>
</div>
.login_container {
  background-color: #409eff;
  height: 100%;
}

.login_box {
  width: 450px;
  height: 300px;
  background-color: #fff;
  border-radius: 3px;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}

3.4.5 繪製預設頭像

<!-- 頭像區域 -->
<div class="avatar_box">
  <img src="../assets/YK.jpg" alt="" />
</div>
.avatar_box {
  height: 130px;
  width: 130px;
  border: 1px solid #eee;
  border-radius: 50%;
  padding: 10px;
  box-shadow: 0 0 10px #ddd;
  position: absolute;
  left: 50%;
  transform: translate(-50%, -50%);
  background-color: #fff;
}
img {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background-color: #eee;
}

3.4.6 繪製登入表單區域

  1. 按需匯入用到的element元件 ./plugins/element.js
import Vue from 'vue'
import { Button, Form, FormItem, Input } from 'element-ui'
Vue.use(Button)
Vue.use(Form)
Vue.use(FormItem)
Vue.use(Input)
  1. 頁面使用引入的元件標籤 Login.vue
<!-- 登入表單區域 -->
<el-form label-width="0px" class="login_form">
  <!-- 使用者名稱 -->
  <el-form-item>
    <el-input></el-input>
  </el-form-item>
  <!-- 密碼 -->
  <el-form-item>
    <el-input></el-input>
  </el-form-item>
  <!-- 按鈕 -->
  <el-form-item>
    <el-button type="primary" class="btns">登入</el-button>
    <el-button type="info">重置</el-button>
  </el-form-item>
</el-form>
.login_form {
  position: absolute;
  bottom: 0;
  width: 100%;
  padding: 0 20px;
  box-sizing: border-box;
}
.btns {
  display: flex;
  justify-content: flex-end;
}

3.4.7 繪製帶icon的input輸入框

https://element.eleme.cn/
官方圖示庫 https://element.eleme.cn/

<el-input prefix-icon="el-icon-user"></el-input>
<el-input prefix-icon="el-icon-lock"></el-input>
  • 阿里字型圖示庫的使用
  1. 下載選好的阿里字型圖示
  2. demo_fontclass.html檢檢視示名稱
  3. 引入iconfont.css樣式表 import './assets/fonts/iconfont.css'
  4. 標籤新增類名 class=「iconfont icon-xxx」

3.4.8 實現表單的資料繫結

<el-form :model="loginForm">
	<el-input v-model="loginForm.username"></el-input>
	<el-input v-model="loginForm.password" type="password"></el-input>
</el-form>
export default {
  data () {
    return {
      // 這是登入表單的資料繫結物件
      loginForm: {
        username: 'admin',
        password: '123456'
      }
    }
  }
}

3.4.9 實現表單的資料驗證

<el-form :rules="loginFormRules">
	<el-form-item prop="username">
		<el-input v-model="loginForm.username"></el-input>
	</el-form-item>
	<el-form-item prop="password">
		<el-input v-model="loginForm.password" type="password"></el-input>
	</el-form-item>
</el-form>
export default {
  data () {
    return {
	  loginFormRules: {
	    // 驗證使用者名稱是否合法
	    username: [
	      { required: true, message: '請輸入登入名稱', trigger: 'blur' },
	      { min: 3, max: 5, message: '長度在 3 到 5 個字元', trigger: 'blur' }
	    ],
	    // 驗證密碼是否合法
	    password: [
	      { required: true, message: '請輸入登入密碼', trigger: 'blur' },
	      { min: 6, max: 15, message: '長度在 6 到 15 個字元', trigger: 'blur' }
	    ]
	  }
	}
  }
}

3.4.10 實現表單的重置功能

  1. 新增參照ref獲取表單範例物件(通過 ref 標註 DOM 元素)
<el-form ref="loginFormRef"></el-form>
  1. 重置按鈕繫結單擊事件
<el-button type="info" @click="resetLoginForm">重置</el-button>
  1. 定義重置方法(通過 $refs 獲取 DOM 元素)
methods: {
  // 點選重置按鈕,重置登入表單
  resetLoginForm () {
    // console.log(this) // VueComponent
    this.$refs.loginFormRef.resetFields()
  }
}

3.4.11 實現登入前表單資料的預驗證,設定axios發起登入請求

  1. 新增點選事件
<el-button type="primary" @click="login">登入</el-button>
  1. 匯入axios包main.js,設定axios
import axios from 'axios'
// 設定請求的根路徑
axios.defaults.baseURL = 'http://127.0.0.1:8888/api/private/v1/'
Vue.prototype.$http = axios
  1. 匯入彈框提示元件element.js
import { Message } from 'element-ui'
Vue.prototype.$message = Message // 彈框提示元件掛在在Vue原型上
  1. 編寫login方法
methods: {
  login () {
    this.$refs.loginFormRef.validate(async (valid) => {
      // console.log(valid) // false/ture
      if (!valid) return
      const { data: result } = await this.$http.post('login', this.loginForm)
      // console.log(result) //Promise
      if (result.meta.status !== 200) return this.$message.error('登入失敗')
      this.$message.success('登入成功')
      
      // 1. 將登入成功之後的 token 儲存到使用者端的 sessionStorage 中(對談期間的儲存機制)(所以不放在loaclStorage中)
      window.sessionStorage.setItem('token', result.data.token)
      // 2. 通過程式設計式導航跳轉到後臺主頁,路由地址是 /home
      this.$router.push('/home')
    })
  }
}
  1. 編寫Home.vue並匯入路由規則
import Home from '../components/Home.vue'
const routes = [  
  { path: '/home', component: Home, }
]

3.4.12 路由導航守衛控制頁面存取許可權

如果使用者沒有登入,但是直接通過URL存取特定頁面,需要重新導航到登入頁面
router/index.js

// 掛載路由導航守衛
router.beforeEach((to, from, next) => {
  // to 將要存取的路徑
  // from 代表從哪個路徑跳轉而來
  // next 是一個函數, 表示放行   ①next()放行   ②next('/login')強制跳轉
  if (to.path === '/login') return next() // 存取登入頁,直接放行
  // 獲取token
  const tokenStr = window.sessionStorage.getItem('token')
  if (!tokenStr) return next('/login') // 沒有token 強制跳轉
  next() // 否則(有token)直接放行
})

3.5 效果展示

在這裡插入圖片描述

3.6 退出功能實現

3.6.1 退出功能實現原理

基於token的方式實現退出比較簡單,只需要銷燬原生的token即可。
這樣,後續的請求就不會攜帶token,必須重新登入生成一個新的token之後才可以存取頁面

3.6.2 具體操作

<el-button type="info" @click="logout">退出</el-button>
methods: {
  logout() {
    window.sessionStorage.clear()
    this.$router.push('/login')
  }
}

3.7 Login 完整程式碼

<template>
  <div class="login_container">
    <div class="login_box">
      <!-- 頭像區域 -->
      <div class="avatar_box">
        <img src="../assets/YK.jpg" alt="" />
      </div>
      <!-- 登入表單區域 -->
      <el-form
        ref="loginFormRef"
        :model="loginForm"
        :rules="loginFormRules"
        label-width="0px"
        class="login_form"
      >
        <!-- 使用者名稱 -->
        <el-form-item prop="username">
          <el-input
            prefix-icon="el-icon-user"
            v-model="loginForm.username"
          ></el-input>
        </el-form-item>
        <!-- 密碼 -->
        <el-form-item prop="password">
          <el-input
            prefix-icon="el-icon-lock"
            v-model="loginForm.password"
            type="password"
          ></el-input>
        </el-form-item>
        <!-- 按鈕 -->
        <el-form-item class="btns">
          <el-button type="primary" @click="login">登入</el-button>
          <el-button type="info" @click="resetLoginForm">重置</el-button>
        </el-form-item>
      </el-form>
    </div>
  </div>
</template>

<script>
export default {
  data () {
    return {
      // 這是登入表單的資料繫結物件
      loginForm: {
        username: 'admin',
        password: '123456'
      },
      // 這是表單驗證規則物件
      loginFormRules: {
        // 驗證使用者名稱是否合法
        username: [
          { required: true, message: '請輸入登入名稱', trigger: 'blur' },
          { min: 3, max: 5, message: '長度在 3 到 5 個字元', trigger: 'blur' }
        ],
        // 驗證密碼是否合法
        password: [
          { required: true, message: '請輸入登入密碼', trigger: 'blur' },
          {
            min: 6,
            max: 15,
            message: '長度在 6 到 15 個字元',
            trigger: 'blur'
          }
        ]
      }
    }
  },
  methods: {
    // 點選重置按鈕,重置登入表單
    resetLoginForm () {
      // console.log(this) // VueComponent
      this.$refs.loginFormRef.resetFields()
    },
    login () {
      this.$refs.loginFormRef.validate(async (valid) => {
        // console.log(valid) // false/ture
        if (!valid) return
        const { data: result } = await this.$http.post('login', this.loginForm)
        // console.log(result)
        if (result.meta.status !== 200) return this.$message.error('登入失敗')
        this.$message.success('登入成功')
        // 將登入成功之後的token 儲存到使用者端的 sessionStorage 中(對談期間的儲存機制)(所以不放在loaclStorage中)
        console.log(result)
        window.sessionStorage.setItem('token', result.data.token)
        // 通過程式設計式導航跳轉到後臺主頁,路由地址是 /home
        this.$router.push('/home')
      })
    }
  }
}
</script>

<style scoped>
.login_container {
  background-color: #409eff;
  height: 100%;
}

.login_box {
  width: 450px;
  height: 300px;
  background-color: #fff;
  border-radius: 3px;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}

.avatar_box {
  height: 130px;
  width: 130px;
  border: 1px solid #eee;
  border-radius: 50%;
  padding: 10px;
  box-shadow: 0 0 10px #ddd;
  position: absolute;
  left: 50%;
  transform: translate(-50%, -50%);
  background-color: #fff;
}

img {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background-color: #eee;
}

.login_form {
  position: absolute;
  bottom: 0;
  width: 100%;
  padding: 0 20px;
  box-sizing: border-box;
}

.btns {
  display: flex;
  justify-content: flex-end;
}
</style>

3.8 將原生程式碼提交到碼雲Gitee中

  1. 檢視檔案狀態
git status
  1. 程式碼新增到快取區
git add .
  1. 提交到本地庫
git commit -m "完成了登入功能"
  1. 檢視分支
git branch
  1. 切換分支到主分支上
git checkout master
  1. 在主分支上合併login分支的程式碼
git merge login
  1. 推播到碼雲中
git push
  1. 檢視碼雲 (只有一個master分支)

https://gitee.com/ykang2020/vue_shop

  1. 將login分支也推播到碼雲中
git checkout login
git push -u origin login

4. 主頁佈局

4.1 整體佈局

<el-container class="home_container">
  <!-- 頭部區域 -->
  <el-header>Header</el-header>
  <!-- 頁面主體區域 -->
  <el-container>
    <!-- 左邊側邊欄 -->
    <el-aside width="200px">Aside</el-aside>
    <!-- 右側內容主體 -->
    <el-main>Main</el-main>
  </el-container>
</el-container>
.home_container {
  height: 100%;
}
.el-header {
  background-color: #373d41;
}
.el-aside {
  background-color: #333744;
}
.el-main {
  background-color: #eaedf1;
}

4.2 美化主頁Header區域

<!-- 頭部區域 -->
<el-header>
  <div>
    <img src="../assets/heima.png" alt="" />
    <span>電商後臺管理系統</span>
  </div>
  <el-button type="info" @click="logout">退出</el-button>
</el-header>
.el-header {
  background-color: #373d41;
  display: flex;
  justify-content: space-between;
  padding-left: 0;
  align-items: center;
  color: #fff;
  font-size: 20px;
}
.el-header > div {
  display: flex;
  align-items: center;
}
.el-header > div > span {
  margin-left: 15px;
}

4.3 實現左側導航選單的基本結構

選單分為二級,並且可以摺疊

<!-- 側邊欄選單區域 -->
<el-menu>
  <el-submenu>
    <!-- 這個 template 是一級選單的內容模板 -->
    <i class="el-icon-menu"></i>
    <span>一級選單</span>
    <!-- 在一級選單中,可以巢狀二級選單 -->
    <el-menu-item>
  	  <i class="el-icon-menu"></i>
  	  <span slot="title">二級選單</span>
  	</el-menu-item>
  </el-submenu>
</el-menu>

4.4 通過axios攔截器新增token驗證

需要授權的 API ,必須在請求頭中使用 Authorization欄位提供 token 令牌

後臺除了登入介面之外,都需要token許可權驗證,我們可以通過新增axios請求攔截器來新增token,以保證擁有獲取資料的許可權
在main.js中新增程式碼,在將axios掛載到vue原型之前新增下面的程式碼

// 通過axios請求攔截器新增token,保證擁有獲取資料的許可權
axios.interceptors.request.use(config => {
  // 為請求頭物件,新增 Token 驗證的 Authorization 欄位
  // console.log(config)
  config.headers.Authorization = window.sessionStorage.getItem('token')
  // 在最後必須 return config
  return config
})

4.5 獲取左側選單資料

Home.vue
頁面載入之前就要獲取資料,定義生命週期函數

data() {
  return {
    // 左側選單資料
    menulist: []
  }
},
created() {
  this.getMenuList()
  this.activePath = window.sessionStorage.getItem('activePath')
},
methods: {
  // 獲取所有的選單
  async getMenuList() {
    const { data: result } = await this.$http.get('menus')
    if (result.meta.status !== 200) return this.$message.error(result.meta.msg)
    this.menulist = result.data
    console.log(result)
  }
}

4.6 通過雙層for迴圈渲染左側選單

<!-- 一級選單 -->
  <el-submenu :index="item.id+''" v-for="item in menulist" :key="item.id">
    <!-- 一級選單的模板區域 -->
    <template slot="title">
      <!-- 文字 -->
      <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>
    <!-- 文字 -->
    <span>{{subItem.authName}}</span>
  </el-menu-item>
</el-submenu>

4.7 為選中項設定字型顏色並新增分類圖示

通過更改el-menu的active-text-color屬性可以設定側邊欄選單中點選的啟用項的文字顏色

<el-menu background-color="#333744" text-color="#fff" active-text-color="rgb(64,158,255)">

通過更改選單項模板(template)中的i標籤的類名,可以將左側選單欄的圖示進行設定

在資料中新增一個iconsObj,然後將圖示類名進行資料繫結

iconsObj: {
  125: 'el-icon-s-custom',
  103: 'el-icon-s-check',
  101: 'el-icon-s-goods',
  102: 'el-icon-s-order',
  145: 'el-icon-s-marketing'
}

一級選單圖示繫結iconsObj中的資料:

<!-- 圖示 -->
<i :class="iconsObj[item.id]"></i>

4.8 每次只能開啟一個選單項並解決邊框問題

為了保持左側選單每次只能開啟一個,顯示其中的子選單,我們可以在el-menu中新增一個屬性unique-opened
或者也可以資料繫結進行設定(此時true認為是一個bool值,而不是字串) :unique-opened=「true」

<el-menu unique-opened>

解決邊框問題

.el-menu {
  border-right: none;
}

4.9 實現側邊欄的摺疊與展開效果

<!-- 左邊側邊欄 -->
<el-aside :width="isCollapse ? '64px':'200px'">
  <div class="toggle-button" @click="toggleCollapse">|||</div>
  <!-- 側邊欄選單區域 -->
  <el-menu :collapse="isCollapse" :collapse-transition="false">
.toggle-button {
  background-color: #4A5064;
  font-size: 10px;
  line-height: 24px;
  color: rgb(144,147,153);
  text-align: center;
  letter-spacing: 0.2em;
  cursor: pointer
}
// 點選按鈕切換選單摺疊與展開
toggleCollapse() {
  this.isCollapse = !this.isCollapse
}

4.10 實現首頁路由的重定向效果

  1. 新增子級路由元件components/Welcome.vue
  2. 在router/index.js中匯入子級路由元件,並設定路由規則以及子級路由的預設重定向
import Welcome from '../components/Welcome.vue'
const routes = [
  {
    path: '/home',
    component: Home,
    redirect: '/welcome',
    children: [{ path: '/welcome', component: Welcome }]
  }
]
  1. 開啟Home.vue,在main的主體結構中新增一個路由預留位置
<!-- 右側內容主體 -->
<el-main>
  <!-- 路由預留位置 -->
  <router-view></router-view>
</el-main>

4.11 實現側邊欄路由連結的改造

  1. 需要將所有的側邊欄二級選單都改造成子級路由連結,我們只需要將el-menu的router屬性設定為true就可以了,此時當我們點選二級選單的時候,就會根據選單的index屬性進行路由跳轉,如: /110,
<el-menu router>
  1. 使用index id來作為跳轉的路徑不合適,我們可以重新系結index的值為:index="’/’+subItem.path"
<!-- 二級選單 -->
<el-menu-item :index="'/'+subItem.path" v-for="subItem in item.children" :key="subItem.id">

4.12 Home完整程式碼

<template>
  <el-container class="home_container">
    <!-- 頭部區域 -->
    <el-header>
      <div>
        <img src="../assets/heima.png" alt="" />
        <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="rgb(64,158,255)"
          unique-opened
          :collapse="isCollapse"
          :collapse-transition="false"
          router
          :default-active="activePath"
        >
        <!-- 一級選單 -->
          <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" @click="saveNavState('/'+subItem.path)">
              <!-- 圖示 -->
              <i class="el-icon-menu"></i>
              <!-- 文字 -->
              <span>{{subItem.authName}}</span>
            </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-s-custom',
        103: 'el-icon-s-check',
        101: 'el-icon-s-goods',
        102: 'el-icon-s-order',
        145: 'el-icon-s-marketing'
      },
      isCollapse: false,
      // 被啟用的連結地址
      activePath: ''
    }
  },
  created() {
    this.getMenuList()
    this.activePath = window.sessionStorage.getItem('activePath')
  },
  methods: {
    logout() {
      window.sessionStorage.clear()
      this.$router.push('/login')
      this.$message.warning('已退出')
    },
    // 獲取所有的選單
    async getMenuList() {
      const { data: result } = await this.$http.get('menus')
      if (result.meta.status !== 200) return this.$message.error(result.meta.msg)
      this.menulist = result.data
      console.log(result)
    },
    // 點選按鈕切換選單摺疊與展開
    toggleCollapse() {
      this.isCollapse = !this.isCollapse
    },
    // 儲存連結的啟用狀態
    saveNavState(activePath) {
      window.sessionStorage.setItem('activePath', activePath)
      this.activePath = activePath
    }
  }
}
</script>

<style scoped>
.home_container {
  height: 100%;
}
.el-header {
  background-color: #373d41;
  display: flex;
  justify-content: space-between;
  padding-left: 0;
  align-items: center;
  color: #fff;
  font-size: 20px;
}
.el-header > div {
  display: flex;
  align-items: center;
}
.el-header > div > span {
  margin-left: 15px;
}
.el-aside {
  background-color: #333744;
}
.toggle-button {
  background-color: #4A5064;
  font-size: 10px;
  line-height: 24px;
  color: rgb(144,147,153);
  text-align: center;
  letter-spacing: 0.2em;
  cursor: pointer
}
.el-menu {
  border-right: none;
}

.el-main {
  background-color: #eaedf1;
}

</style>

5. 展示

在這裡插入圖片描述
專案地址https://gitee.com/ykang2020/vue_shop