表单数据绑定
<!-- 登录表单区域 --> <el-form :model="loginForm" class="login_form"> <!-- 用户名 --> <el-form-item> <el-input v-model="loginForm.username" prefix- icon="iconfont icon-user"></el-input> </el-form-item> <!-- 密码 --> <el-form-item> <el-input v-model="loginForm.password" prefix- icon="iconfont icon-3702mima" type="password"></el-input> //type指定为密码,可以将输入框中的密码隐藏 </el-form-item> </el-form>
<script> export default { data () { return { // 这是登录表单的数据绑定对象 loginForm: { username: '', password: '' } } } } </script>
el-form中使用属性:model绑定一个数组,这个数组在data里面定义
el-input使用v-model绑定loginForm数组中的字段
表单数据验证
form通过 rules
属性传入约定的验证规则,并将 Form-Item 的 prop
属性设置为需校验的字段名即可
<el-form :model="loginForm" :rules="loginFormRules" class="login_form"> <!-- 用户名 --> <el-form-item prop="username"> <el-input v-model="loginForm.username" prefix-icon="iconfont icon-user"></el-input> </el-form-item> <!-- 密码 --> <el-form-item prop="password"> <el-input v-model="loginForm.password" prefix-icon="iconfont icon-3702mima" type="password"></el-input> </el-form-item> </el-form>
export default { data () { return { // 登录表单的数据绑定对象 loginForm: { username: '', password: '' }, // 表单的验证规则对象 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' } ] }//required:true表示必填项,message表示提示信息, trigger:'blur'表示获得焦点时触发事件 } } }
实现表单重置
form中通过ref获取表单信息,重置button写一个点击事件
<el-form ref="loginFormRef" :model="loginForm" :rules="loginFormRules" class="login_form">
<el-button type="info" @click="resetLoginForm">重置</el-button>
methods: { // 重置按钮点击事件 resetLoginForm () { // console.log(this)这个this打印出来有$ref this.$refs.loginFormRef.resetFields() } }
resetFields ( )方法对整个表单进行重置,将所有字段值重置为初始值并移除校验结果
登录前的预验证
validate()方法对整个表单进行校验的方法,参数为一个回调函数。该回调函数会在校验结束后被调用,并传入两个参数:是否校验成功(Boolean)和未通过校验的字段。若不传入回调函数,则会返回一个 promise
<el-button type="primary" @click="login">登录</el-button>
login () { this.$refs.loginFormRef.validate(valid => { console.log(valid) }) }//valid即为返回的验证结果(Boolean类型)
输入正确用户名密码,后台打印true
根据预验证是否发起请求
axios全局配置
发起请求需要用到axios,那么首先要在main.js中对axios进行全局配置
// axios全局配置 import axios from 'axios'//导入包 // 配置请求的根路径(API接口) axios.defaults.baseURL = 'https://lianghj.top:8888/api/private/v1/' Vue.prototype.$http = axios//把包挂载到vue的原型对象上去 这样每一个vue组件都可以通过this访问到$http,从而发起axios请求
通过API接口文档
(\20-21vue电商\3.vue-项目实战day1\素材)
查阅到登录验证接口(具体内容可查看文档)
使用axios.post
login () { this.$refs.loginFormRef.validate(valid => { if (!valid) return // 如果是false就返回,true发起请求 this.$http.post('login', this.loginForm) // 第一个参数为请求地址(路径),第二个请求参数为表单信息,,,,这里的$http.post实际上就是axios.post请求 }) }
然后打开PHPstudy打开mysql(无法启动,可能是因为3306端口被mysqlid占用,这时候需要结束此进程,再去启动mysql就可以正常启动),进入\3.vue-项目实战day1\素材\vue_api_server路径按住shift右击打开powerShell窗口运行app.js(node ./app.js)无error报错即为运行成功
下面使用result接收数据(相当于项目中的res)
const result = this.$http.post('login',this.loginForm) console.log(result)
返回promise
Async和Await简化Promise
async + await 必须配合 promise 使用,同时 async 和 await 必须一起使用。即 await 必须在 async 标记的函数中使用
async + await 的作用: 简化 promise 的异步操作,把 promise 的异步操作编程变为同步的写法
async 将一个函数标记为异步函数,await 需要在异步函数中使用,标记当前操作是异步操作。
login () { this.$refs.loginFormRef.validate(async valid => { if (!valid) return// 如果是false就返回 const result = await this.$http.post('login', this.loginForm) console.log(result) }) }
后台打印输出具体的响应对象而不是promise
data中有6个数据,data是服务器返回的真实数据,其他五个都是axios封装好的。
取出data:
const { data: res } = await this.$http.post('login', this.loginForm) console.log(res)//把data单独赋值输出,这里打印出来的只有data
login登录方法最终代码:
//判断status并返回结果 login () { this.$refs.loginFormRef.validate(async valid => { if (!valid) return const { data: res } = await this.$http.post('login', this.loginForm) if (res.meta.status !== 200) return console.log('登录失败') console.log('登录成功') }) }
配置弹窗提醒
前面只是用console在控制台输出,这里点击登录出现弹窗,让用户知道登录成功还是登录失败
这里老师使用$message还配置了element.js文件,但是我这里的element.js代码如下(新版),不需要一个一个的配置
import Vue from 'vue' import Element from 'element-ui' import 'element-ui/lib/theme-chalk/index.css' Vue.use(Element) //应该是直接导入全部的element组件
使用$message提供的success和error方法:
if (res.meta.status !== 200) return this.$message.error('登录失败!') this.$message.success('登录成功!')
登录成功后的行为
token保存到sessionStorage中
将登录成功之后的token保存到客户端的sessionStorage中
为什么要保存token?
项目中除了登录之外的其他API接口,必须在登录之后才能访问(即登录之后携带token才能访问)
为什么要保存在sessionStorage中?
token只应在当前网站打开期间生效,所以将token保存在sessionStorage中
console.log打印一下data
可以发现data中有一个token,我们将它保存到sessionStorage中
sessionStorage解读:
在编写程序过程中,用到sessionStorage方法存储一个数据,会大大方便代码的编写,使用sessionStorage创建一个本地的存储,以key/value的形式,该键值对可以直接保存在浏览器中供我们使用,sessionStorage用于临时存储同一窗口或标签页的数据,当关闭该窗口或者标签页后,该数据随之删除,如果想浏览器窗口关闭后还保留数据,则可以使用localStorage,该存储的数据会一直存在,除非自己手动删除。
常用语句就是存储,读取数据,
存储:window.sessionStorage.setItem(key,value);
读取:window.sessionStorage.getItem(key),返回value值
后台查看SessionStorage:(点击登录按钮后有token数据)
跳转到后台主页
通过编程式导航跳转到后台主页,路由地址是 /home
this.$router.push() 可以通过修改url实现路由跳转。
新建页面Home.vue
router>index.js导入Home文件,并创建一个路由规则
路由导航守卫控制访问权限
如果用户没有登录(获取不到token),但是直接通过URL访问特定页面,需要重新导航到登录页面
router>index.js
const routes = [ { path: '/', redirect: '/login' }, { path: '/login', component: Login }, { path: '/home', component: Home } ] const router = new VueRouter({ routes }) // 挂载路由导航守卫 router.beforeEach((to, from, next) => { // to表示将要访问的路径 // from代表从哪个路径跳转而来 // next 是一个函数,表示放行(可以访问) // 两种使用方式: next()放行 next('/login')强制跳转 // 访问登录页,直接放行(登录页不需要token也可以访问) if (to.path === '/login') return next() // 不是访问登录页 获取token const tokenStr = window.sessionStorage.getItem('token') // 未获取到token,强制跳转至登录页 if (!tokenStr) return next('/login') // 获取到token,直接放行 next() }) export default router
验证:先打开后台管理器Application>SessionStorage>token
①当sessionStorage中没有token时无法访问/home页面
②点击登录,获取到了token,跳转到了home页面,
③清除token,从home页面强制跳转到了login页面
退出功能实现原理
基于token的方式实现退出比较简单,只需要销毁本地的token即可。这样,后续的请求就不会携带token,必须重新登录生成一个新的token之后才可以访问页面。
Home.vue:
<template> <div> <el-button type="info" @click="logout">退出</el- button> </div> </template> <script> export default { methods: { logout () { window.sessionStorage.clear() this.$router.push('/login') } } } </script>
处理语法警告问题
login()这个方法和括号之间如果没有空格就会报错,禁用此语法规则,即可解决报错提醒
打开eslintrc.js文件,rules下加一句'space-before-function-paren': 0
rules: { 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off', 'space-before-function-paren': 0 //让此语法始终为0 }
提交登录功能代码
使用快捷键Ctrl+`(esc下面的那个键~)打开终端
下面这部分需要在敲代码之前将分支切换到login分支
输入git status
PS C:\Users\liybi\Desktop\学习笔记\vue\vue_shop> git status On branch master Changes not staged for commit: (use "git add/rm <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: .eslintrc.js modified: package-lock.json modified: package.json modified: src/App.vue deleted: src/components/HelloWorld.vue modified: src/main.js modified: src/router/index.js deleted: src/views/AboutView.vue deleted: src/views/HomeView.vue modified: vue.config.js Untracked files: (use "git add <file>..." to include in what will be committed) src/assets/css/ src/assets/fonts/ src/components/Home.vue src/components/Login.vue src/plugins/ no changes added to commit (use "git add" and/or "git commit -a")
上面的文件是修改过的,下面的文件是新建的
输入git add . 将这些文件添加到暂存区
git status文件都变成绿色说明,这些文件都添加到了暂存区
下面将暂存区代码提交的本地仓库:git commit -m "提交消息"
-m参数就是用来添加提交消息的
git branch
当前在login分支,就说明刚才提交的都提交到了login分支
我们需要合并到主分支master,首先进入主分支
git checkout master(checkout表示切换分支)
git merge login (merge用于合并分支)将login合并到当前分支master
git branch
git push提交到码云
git checkout login切换到login分支 (前提是之前创建了此分支,若没有创建则会出现
git checkout -b login创建并切换到login分支
但是这里重新新建然后推送到origin中好像没有意义,因为这个分支里面没有东西,应该是刚开始写这一部分功能的时候新建此分支然后在此分支下写功能,然后再将login合并到master,push到码云,然后将login分支推送到origin仓储里面
git branch查看一下分支
git push -u origin login将login分支推送到云端origin仓储里面