今日目标

1.初始化项目
2.基于Vue技术栈进行项目开发
3.使用Vue的第三方组件进行项目开发
4.理解前后端分离开发模式

1.电商业务概述

客户使用的业务服务:PC端,小程序,移动web,移动app
管理员使用的业务服务:PC后台管理端。
PC后台管理端的功能:管理用户账号(登录,退出,用户管理,权限管理),商品管理(商品分类,分类参数,商品信息,订单),数据统计
电商后台管理系统采用前后端分离的开发模式
前端项目是基于Vue的SPA(单页应用程序)项目
前端技术栈:Vue,Vue-Router,Element-UI,Axios,Echarts
后端技术栈:Node.js,Express,Jwt(模拟session),Mysql,Sequelize(操作数据库的框架)

2.项目初始化

A.安装Vue脚手架
B.通过脚手架创建项目
C.配置路由
D.配置Element-UI:在插件中安装,搜索vue-cli-plugin-element
E.配置Axios:在依赖中安装,搜索axios(运行依赖)
F.初始化git仓库
G.将本地项目托管到github或者码云中

3.码云相关操作

A.注册登录码云账号
day07 - 图1
B.安装git
在Windows上使用Git,可以从Git官网直接下载安装程序进行安装。
测试命令:git —version
C.点击网站右上角“登录”,登录码云,并进行账号设置
day07 - 图2
D.在本地创建公钥:在终端运行:ssh-keygen -t rsa -C “xxx@xxx.com
day07 - 图3
E.找到公钥地址:
Your identification has been saved in /c/Users/My/.ssh/id_rsa.
Your public key has been saved in /c/Users/My/.ssh/id_rsa.pub.
当我们创建公钥完毕之后,请注意打印出来的信息“Your public key has been saved in”
/c/Users/My/.ssh/id_rsa.pub : c盘下面的Users下面的My下面的.ssh下面的id_rsa.pub就是我们创建好的公钥了
E.打开id_rsa.pub文件,复制文件中的所有代码,点击码云中的SSH公钥,将生成的公钥复制到公钥中
day07 - 图4
day07 - 图5
G.测试公钥:打开终端,输入命令
ssh -T git@gitee.com
day07 - 图6
H.将本地代码托管到码云中
点击码云右上角的+号->新建仓库
day07 - 图7
day07 - 图8
I.进行git配置:
day07 - 图9
打开项目所在位置的终端,进行git仓库关联
day07 - 图10

4.配置后台项目

A.安装phpStudy并导入mysql数据库数据
day07 - 图11
day07 - 图12
B.安装nodeJS,配置后台项目,从终端打开后台项目vue_api_server
然后在终端中输入命令安装项目依赖包:npm install
C.使用postman测试api接口
day07 - 图13

5.实现登录功能

A.登录状态保持
如果服务器和客户端同源,建议可以使用cookie或者session来保持登录状态
如果客户端和服务器跨域了,建议使用token进行维持登录状态。
B.登录逻辑:
在登录页面输入账号和密码进行登录,将数据发送给服务器
服务器返回登录的结果,登录成功则返回数据中带有token
客户端得到token并进行保存,后续的请求都需要将此token发送给服务器,服务器会验证token以保证用户身份。
C.添加新分支login,在login分支中开发当前项目vue_shop:
打开vue_shop终端,使用git status确定当前项目状态。
确定当前工作目录是干净的之后,创建一个分支进行开发,开发完毕之后将其合并到master
git checkout -b login
然后查看新创建的分支:git branch
确定我们正在使用login分支进行开发
day07 - 图14
然后执行vue ui命令打开ui界面,然后运行serve,运行app查看当前项目效果
day07 - 图15
发现现在是一个默认页面,我们需要进行更改,打开项目的src目录,点击main.js文件(入口文件)

  1. import Vue from 'vue'
  2. import App from './App.vue'
  3. import router from './router'
  4. import './plugins/element.js'
  5. Vue.config.productionTip = false
  6. new Vue({
  7. router,
  8. render: h => h(App)
  9. }).$mount('#app')

再打开App.vue(根组件),将根组件的内容进行操作梳理(template中留下根节点,script中留下默认导出,去掉组件,style中去掉所有样式)

  1. <template>
  2. <div id="app">
  3. <router-view></router-view>
  4. </div>
  5. </template>
  6. <script>
  7. export default {
  8. name: 'app'
  9. }
  10. </script>
  11. <style>
  12. </style>

再打开router.js(路由),将routes数组中的路由规则清除,然后将views删除,将components中的helloworld.vue删除

  1. import Vue from 'vue'
  2. import Router from 'vue-router'
  3. Vue.use(Router)
  4. export default new Router({
  5. routes: [
  6. ]
  7. })

在components文件夹中新建Login.vue组件,添加template,script,style标签,style标签中的scoped可以防止组件之间的样式冲突,没有scoped则样式是全局的

  1. <template>
  2. <div class="login_container">
  3. </div>
  4. </template>
  5. <script>
  6. export default {
  7. }
  8. </script>
  9. <style lang="less" scoped>
  10. .login_container {
  11. background-color: #2b5b6b;
  12. height: 100%;
  13. }
  14. </style>

在router.js中导入组件并设置规则
在App.vue中添加路由占位符

  1. const router = new Router({
  2. routes: [
  3. { path: '/', redirect: '/login' },//重定向
  4. { path: '/login', component: Login }
  5. ]
  6. })

当我们给Login.vue中的内容添加样式的时候,会报错“缺少less-loader”,需要配置less加载器(开发依赖),安装less(开发依赖)
day07 - 图16
然后需要添加公共样式,在assets文件夹下面添加css文件夹,创建global.css文件,添加全局样式

  1. /* 全局样式表 */
  2. html,body,#app{
  3. width: 100%;
  4. height: 100%;
  5. margin: 0;
  6. padding: 0;
  7. }

在main.js中导入global.css,使得全局样式生效 import “./assets/css/global.css”
然后Login.vue中的根元素也需要设置撑满全屏(height:100%)
最终Login.vue文件中的代码如下

  1. <template>
  2. <div class="login_container">
  3. <!-- 登录盒子 -->
  4. <div class="login_box">
  5. <!-- 头像 -->
  6. <div class="avatar_box">
  7. <img src="../assets/logo.png" alt="">
  8. </div>
  9. <!-- 登录表单 -->
  10. <el-form :model="loginForm" ref="LoginFormRef" :rules="loginFormRules" label-width="0px" class="login_form">
  11. <!-- 用户名 -->
  12. <el-form-item prop="username">
  13. <el-input v-model="loginForm.username" prefix-icon="iconfont icon-user" ></el-input>
  14. </el-form-item>
  15. <!-- 密码 -->
  16. <el-form-item prop="password">
  17. <el-input type="password" v-model="loginForm.password" prefix-icon="iconfont icon-3702mima"></el-input>
  18. </el-form-item>
  19. <!-- 按钮 -->
  20. <el-form-item class="btns">
  21. <el-button type="primary" @click="login">登录</el-button>
  22. <el-button type="info" @click="resetLoginForm">重置</el-button>
  23. </el-form-item>
  24. </el-form>
  25. </div>
  26. </div>
  27. </template>
  28. <script>
  29. export default {
  30. data() {
  31. return {
  32. //数据绑定
  33. loginForm: {
  34. username: 'admin',
  35. password: '123456'
  36. },
  37. //表单验证规则
  38. loginFormRules: {
  39. username: [
  40. { required: true, message: '请输入登录名', trigger: 'blur' },
  41. {
  42. min: 3,
  43. max: 10,
  44. message: '登录名长度在 3 到 10 个字符',
  45. trigger: 'blur'
  46. }
  47. ],
  48. password: [
  49. { required: true, message: '请输入密码', trigger: 'blur' },
  50. {
  51. min: 6,
  52. max: 15,
  53. message: '密码长度在 6 到 15 个字符',
  54. trigger: 'blur'
  55. }
  56. ]
  57. }
  58. }
  59. },
  60. //添加行为,
  61. methods: {
  62. //添加表单重置方法
  63. resetLoginForm() {
  64. //this=>当前组件对象,其中的属性$refs包含了设置的表单ref
  65. // console.log(this)
  66. this.$refs.LoginFormRef.resetFields()
  67. },
  68. login() {
  69. //点击登录的时候先调用validate方法验证表单内容是否有误
  70. this.$refs.LoginFormRef.validate(async valid => {
  71. console.log(this.loginFormRules)
  72. //如果valid参数为true则验证通过
  73. if (!valid) {
  74. return
  75. }
  76. //发送请求进行登录
  77. const { data: res } = await this.$http.post('login', this.loginForm)
  78. // console.log(res);
  79. if (res.meta.status !== 200) {
  80. return this.$message.error('登录失败:' + res.meta.msg) //console.log("登录失败:"+res.meta.msg)
  81. }
  82. this.$message.success('登录成功')
  83. console.log(res)
  84. //保存token
  85. window.sessionStorage.setItem('token', res.data.token)
  86. // 导航至/home
  87. this.$router.push('/home')
  88. })
  89. }
  90. }
  91. }
  92. </script>
  93. <style lang="less" scoped>
  94. .login_container {
  95. background-color: #2b5b6b;
  96. height: 100%;
  97. }
  98. .login_box {
  99. width: 450px;
  100. height: 300px;
  101. background: #fff;
  102. border-radius: 3px;
  103. position: absolute;
  104. left: 50%;
  105. top: 50%;
  106. transform: translate(-50%, -50%);
  107. .avatar_box {
  108. height: 130px;
  109. width: 130px;
  110. border: 1px solid #eee;
  111. border-radius: 50%;
  112. padding: 10px;
  113. box-shadow: 0 0 10px #ddd;
  114. position: absolute;
  115. left: 50%;
  116. transform: translate(-50%, -50%);
  117. background-color: #fff;
  118. img {
  119. width: 100%;
  120. height: 100%;
  121. border-radius: 50%;
  122. background-color: #eee;
  123. }
  124. }
  125. }
  126. .login_form {
  127. position: absolute;
  128. bottom: 0;
  129. width: 100%;
  130. padding: 0 20px;
  131. box-sizing: border-box;
  132. }
  133. .btns {
  134. display: flex;
  135. justify-content: flex-end;
  136. }
  137. </style>

其中我们有用到一下内容,需要进行进一步处理:
A.添加element-ui的表单组件
在plugins文件夹中打开element.js文件,进行elementui的按需导入
import Vue from ‘vue’
import { Button } from ‘element-ui’
import { Form, FormItem } from ‘element-ui’
import { Input } from ‘element-ui’
Vue.use(Button)
Vue.use(Form)
Vue.use(FormItem)
Vue.use(Input)
B.添加第三方字体
复制素材中的fonts文件夹到assets中,在入口文件main.js中导入import ‘./assets/fonts/iconfont.css’
然后直接在
接着添加登录盒子
C.添加表单验证的步骤
1).给添加属性:rules=”rules”,rules是一堆验证规则,定义在script、中
2).在script中添加rules:export default{ data(){return{……, rules: {
name: [
{ required: true, message: ‘请输入活动名称’, trigger: ‘blur’ },
{ min: 3, max: 5, message: ‘长度在 3 到 5 个字符’, trigger: ‘blur’ }
],
region: [
{ required: true, message: ‘请选择活动区域’, trigger: ‘change’ }
]
}……
3).通过的prop属性设置验证规则
4.导入axios以发送ajax请求
打开main.js,import axios from ‘axios’;
设置请求的根路径:axios.defaults.baseURL = ‘http://127.0.0.1:8888/api/private/v1/‘;
挂载axios:Vue.prototype.$http = axios;
5.配置弹窗提示:
在plugins文件夹中打开element.js文件,进行elementui的按需导入
import {Message} from ‘element-ui’
进行全局挂载:Vue.prototype.message.error(‘登录失败’)

6.登录成功之后的操作

A.登录成功之后,需要将后台返回的token保存到sessionStorage中
操作完毕之后,需要跳转到/home

  1. login() {
  2. //点击登录的时候先调用validate方法验证表单内容是否有误
  3. this.$refs.LoginFormRef.validate(async valid => {
  4. console.log(this.loginFormRules)
  5. //如果valid参数为true则验证通过
  6. if (!valid) {
  7. return
  8. }
  9. //发送请求进行登录
  10. const { data: res } = await this.$http.post('login', this.loginForm)
  11. // console.log(res);
  12. if (res.meta.status !== 200) {
  13. return this.$message.error('登录失败:' + res.meta.msg)
  14. //console.log("登录失败:"+res.meta.msg)
  15. }
  16. this.$message.success('登录成功')
  17. console.log(res)
  18. //保存token
  19. window.sessionStorage.setItem('token', res.data.token)
  20. // 导航至/home
  21. this.$router.push('/home')
  22. })
  23. }

添加一个组件Home.vue,并为之添加规则

  1. <template>
  2. <div>
  3. this is home
  4. <el-button type="info" @click="logout"> 退出 </el-button>
  5. </div>
  6. </template>
  7. <script>
  8. export default {
  9. methods: {
  10. logout() {
  11. window.sessionStorage.clear()
  12. this.$router.push('/login')
  13. }
  14. }
  15. }
  16. </script>
  17. <style lang='less' scoped>
  18. </style>

添加路由规则

  1. const router = new Router({
  2. routes: [
  3. { path: '/', redirect: '/login' },
  4. { path: '/login', component: Login },
  5. { path: '/home', component: Home }
  6. ]
  7. })

添加路由守卫
如果用户没有登录,不能访问/home,如果用户通过url地址直接访问,则强制跳转到登录页面
打开router.js

  1. import Vue from 'vue'
  2. import Router from 'vue-router'
  3. import Login from './components/Login.vue'
  4. import Home from './components/Home.vue'
  5. Vue.use(Router)
  6. const router = new Router({
  7. routes: [
  8. { path:'/', redirect:'/login'},
  9. { path:'/login' , component:Login },
  10. { path:'/home' , component:Home}
  11. ]
  12. })
  13. //挂载路由导航守卫,to表示将要访问的路径,from表示从哪里来,next是下一个要做的操作
  14. router.beforeEach((to,from,next)=>{
  15. if(to.path === '/login')
  16. return next();
  17. //获取token
  18. const tokenStr = window.sessionStorage.getItem('token');
  19. if(!tokenStr)
  20. return next('/login');
  21. next();
  22. })
  23. export default router

实现退出功能
在Home组件中添加一个退出功能按钮,给退出按钮添加点击事件,添加事件处理代码如下:

  1. export default {
  2. methods:{
  3. logout(){
  4. window.sessionStorage.clear();
  5. this.$router.push('/login');
  6. }
  7. }
  8. }

补充

A.处理ESLint警告
打开脚手架面板,查看警告信息
[图片]
默认情况下,ESLint和vscode格式化工具有冲突,需要添加配置文件解决冲突。
在项目根目录添加 .prettierrc 文件

  1. {
  2. "semi":false,
  3. "singleQuote":true
  4. }

打开.eslintrc.js文件,禁用对 space-before-function-paren 的检查:

  1. rules: {
  2. 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
  3. 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
  4. 'space-before-function-paren' : 0
  5. },

B.合并按需导入的element-ui

  1. import Vue from 'vue'
  2. import { Button, Form, FormItem, Input, Message } from 'element-ui'
  3. Vue.use(Button)
  4. Vue.use(Form)
  5. Vue.use(FormItem)
  6. Vue.use(Input)
  7. // 进行全局挂载:
  8. Vue.prototype.$message = Message

C.将代码提交到码云
新建一个项目终端,输入命令‘git status’查看修改过的与新增的文件内容
将所有文件添加到暂存区:git add .
将所有代码提交到本地仓库:git commit -m “添加登录功能以及/home的基本结构”
查看分支: git branch 发现所有代码都被提交到了login分支
将login分支代码合并到master主分支,先切换到master:git checkout master
在master分支进行代码合并:git merge login
将本地的master推送到远端的码云:git push
推送本地的子分支到码云,先切换到子分支:git checkout 分支名
然后推送到码云:git push -u origin 远端分支名