600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > 【Vue】实战项目:电商后台管理系统(Element-UI)(一)前后端搭建 - 登录界面 - 主页界面

【Vue】实战项目:电商后台管理系统(Element-UI)(一)前后端搭建 - 登录界面 - 主页界面

时间:2022-12-17 07:11:55

相关推荐

【Vue】实战项目:电商后台管理系统(Element-UI)(一)前后端搭建 - 登录界面 - 主页界面

文章目录

0. 项目介绍电商管理系统(Element-UI)开发模式前端技术栈后端技术栈1. 配置——初始化 前端项目① 安装 Vue 脚手架② 通过 Vue 脚手架创建项目③ 配置 Vue 路由④ 配置 Element-UI 组件库⑤ 配置 axios 库⑥ 语法处理ESLint⑦ 初始化 git 远程仓库⑧ 将本地项目托管到 Github 或 码云 中2. 配置后端接口① 安装 MySQL 数据库② 安装 Node.js 环境③ 配置项目相关信息④ 启动项目⑤查看API文档电商管理后台 API 接口文档.md⑥ 使用 Postman 测试后台项目接口是否正常3. 登录/退出功能3.1 登录业务流程3.2 登录业务的相关技术点3.3 token原理3.4 登录功能实现3.4.1 布局分析3.4.2 Git 创建login分支3.4.3 渲染Login组件并实现路由重定向3.4.4 设置背景颜色并在屏幕中央绘制登录盒子3.4.5 绘制默认头像3.4.6 绘制登录表单区域3.4.7 绘制带icon的input输入框3.4.8 实现表单的数据绑定3.4.9 实现表单的数据验证3.4.10 实现表单的重置功能3.4.11 实现登录前表单数据的预验证,配置axios发起登录请求3.4.12 路由导航守卫控制页面访问权限3.5 效果展示3.6 退出功能实现3.6.1 退出功能实现原理3.6.2 具体操作3.7 Login 完整代码3.8 将本地代码提交到码云Gitee中4. 主页布局4.1 整体布局4.2 美化主页Header区域4.3 实现左侧导航菜单的基本结构4.4 通过axios拦截器添加token验证4.5 获取左侧菜单数据4.6 通过双层for循环渲染左侧菜单4.7 为选中项设置字体颜色并添加分类图标4.8 每次只能打开一个菜单项并解决边框问题4.9 实现侧边栏的折叠与展开效果4.10 实现首页路由的重定向效果4.11 实现侧边栏路由链接的改造4.12 Home完整代码5. 展示

项目地址/ykang/vue_shop

0. 项目介绍

电商管理系统(Element-UI)

电商后台管理系统用于管理用户账号、商品分类、商品信息、订单、数据统计等业务功能

开发模式

电商后台管理系统整体采用前后端分离的开发模式,其中前端项目是基于 Vue 技术栈的 SPA(单页应用程序) 项目

前端技术栈

VueVue-routerElement-UIAxiosEcharts

后端技术栈

Node.jsExpressJwt(模拟session)MysqlSequelize(操作数据库的框架)

1. 配置——初始化 前端项目

① 安装 Vue 脚手架

② 通过 Vue 脚手架创建项目

③ 配置 Vue 路由

④ 配置 Element-UI 组件库

⑤ 配置 axios 库

⑥ 语法处理ESLint

⑦ 初始化 git 远程仓库

⑧ 将本地项目托管到 Github 或 码云 中

详见【Vue】vue-cli - 图形化创建项目 - 配置项目 - axios - elementUI - 码云SSH公钥设置 - Gitee同步

2. 配置后端接口

① 安装 MySQL 数据库

使用phpStudy软件(关闭Apache)

导入数据库文件(路径不能有中文)

检查数据 里面有数据说明导入完成

② 安装 Node.js 环境

③ 配置项目相关信息

cd E:\YKcode\web\myProject01\api\vue_api_servercnpm install

④ 启动项目

出错了就多npm installcnpm install几下

node app.js

⑤查看API文档电商管理后台 API 接口文档.md

![在这里插入图片描述](https://img-/0314154316727.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-formel-form-itemel-inputel-button字体图标

3.4.2 Git 创建login分支

创建分支

git checkout -b login

查看分支

git branch

3.4.3 渲染Login组件并实现路由重定向

清空Vue模板和路由 main.js App.vue ./components/HelloWorld.vue ./views创建组件 ./view/Login.vue添加路由规则 ./router/index.js 设置默认页面重定向到login

import Login from '../components/Login.vue'const routes = [{path: '/', redirect: '/login' },{path: '/login', component: Login }]

添加路由占位符 App.vue

<div id="app"><!-- 路由占位符 --><router-view></router-view></div>

3.4.4 设置背景颜色并在屏幕中央绘制登录盒子

在可视化工具中安装开发依赖less 和 less-loader安装过依赖后要重新编译设置全局样式 ./assets/css/global.css

/* 全局样式表 */html,body,#app {height: 100%;margin: 0;padding: 0;min-width: 1366px;}

入口文件导入全局css文件 ./main.js

// 导入全局样式表import './assets/css/global.css'

设置背景颜色并在屏幕中央绘制登录盒子 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 绘制登录表单区域

按需导入用到的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)

页面使用引入的组件标签 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输入框

/#/zh-CN/component/input

官方图标库 /#/zh-CN/component/icon

<el-input prefix-icon="el-icon-user"></el-input>

<el-input prefix-icon="el-icon-lock"></el-input>

阿里字体图标库的使用 下载选好的阿里字体图标demo_fontclass.html查看图标名称引入iconfont.css样式表import './assets/fonts/iconfont.css'标签添加类名 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 实现表单的重置功能

添加引用ref获取表单实例对象(通过 ref 标注 DOM 元素)

<el-form ref="loginFormRef"></el-form>

重置按钮绑定单击事件

<el-button type="info" @click="resetLoginForm">重置</el-button>

定义重置方法(通过 $refs 获取 DOM 元素)

methods: {// 点击重置按钮,重置登录表单resetLoginForm () {// console.log(this) // VueComponentthis.$refs.loginFormRef.resetFields()}}

3.4.11 实现登录前表单数据的预验证,配置axios发起登录请求

添加点击事件

<el-button type="primary" @click="login">登录</el-button>

导入axios包main.js,配置axios

import axios from 'axios'// 配置请求的根路径axios.defaults.baseURL = 'http://127.0.0.1:8888/api/private/v1/'Vue.prototype.$http = axios

导入弹框提示组件element.js

import {Message } from 'element-ui'Vue.prototype.$message = Message // 弹框提示组件挂在在Vue原型上

编写login方法

methods: {login () {this.$refs.loginFormRef.validate(async (valid) => {// console.log(valid) // false/tureif (!valid) returnconst {data: result } = await this.$http.post('login', this.loginForm)// console.log(result) //Promiseif (result.meta.status !== 200) return this.$message.error('登录失败')this.$message.success('登录成功')// 1. 将登录成功之后的 token 保存到客户端的 sessionStorage 中(会话期间的存储机制)(所以不放在loaclStorage中)window.sessionStorage.setItem('token', result.data.token)// 2. 通过编程式导航跳转到后台主页,路由地址是 /homethis.$router.push('/home')})}}

编写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() // 访问登录页,直接放行// 获取tokenconst 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-formref="loginFormRef":model="loginForm":rules="loginFormRules"label-width="0px"class="login_form"><!-- 用户名 --><el-form-item prop="username"><el-inputprefix-icon="el-icon-user"v-model="loginForm.username"></el-input></el-form-item><!-- 密码 --><el-form-item prop="password"><el-inputprefix-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) // VueComponentthis.$refs.loginFormRef.resetFields()},login () {this.$refs.loginFormRef.validate(async (valid) => {// console.log(valid) // false/tureif (!valid) returnconst {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)// 通过编程式导航跳转到后台主页,路由地址是 /homethis.$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中

查看文件状态

git status

代码添加到缓存区

git add .

提交到本地库

git commit -m "完成了登录功能"

查看分支

git branch

切换分支到主分支上

git checkout master

在主分支上合并login分支的代码

git merge login

推送到码云中

git push

查看码云 (只有一个master分支)

/ykang/vue_shop

将login分支也推送到码云中

git checkout logingit 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 configreturn 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.dataconsole.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 实现首页路由的重定向效果

新增子级路由组件components/Welcome.vue在router/index.js中导入子级路由组件,并设置路由规则以及子级路由的默认重定向

import Welcome from '../components/Welcome.vue'const routes = [{path: '/home',component: Home,redirect: '/welcome',children: [{path: '/welcome', component: Welcome }]}]

打开Home.vue,在main的主体结构中添加一个路由占位符

<!-- 右侧内容主体 --><el-main><!-- 路由占位符 --><router-view></router-view></el-main>

4.11 实现侧边栏路由链接的改造

需要将所有的侧边栏二级菜单都改造成子级路由链接,我们只需要将el-menu的router属性设置为true就可以了,此时当我们点击二级菜单的时候,就会根据菜单的index属性进行路由跳转,如: /110,

<el-menu router>

使用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-menubackground-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.dataconsole.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. 展示

项目地址/ykang/vue_shop

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。