登录
01-完成静态页面
添加一个登录页面:
- 创建一个 login 组件
- 设置 login 路由
- 完成静态页面
代码:
<template>
<div>
<van-form>
<!-- navbar导航栏 -->
<van-nav-bar title="标题"></van-nav-bar>
<!-- 用户名密码输入框 -->
<van-cell-group>
<van-field v-model="user.mobile" placeholder="请输入手机号">
<template #left-icon>
<i class="iconfont icon-phone"></i>
</template>
</van-field>
<van-field v-model="user.code" placeholder="请输入验证码">
<template #left-icon>
<i class="iconfont icon-lock1"></i>
</template>
<template #button>
<van-button class="codebtn" size="small" color="#ececec" round>获取验证码</van-button>
</template>
</van-field>
</van-cell-group>
<!-- 登录按钮 -->
<div class="loginbtn">
<van-button type="info" size="large">登录</van-button>
</div>
</van-form>
</div>
</template>
<script>
export default {
data () {
return {
user: {
mobile: '', // 手机号
code: '' // 验证码
}
}
}
}
</script>
<style lang="less" scoped>
.van-nav-bar.van-hairline--bottom {
background-color: #3596fa;
}
/deep/ .van-nav-bar__title.van-ellipsis {
color: #fff;
}
.codebtn {
.van-button__text{
color: #666;
}
}
.loginbtn {
margin: 20px;
.van-button {
border-radius: 10px;
}
}
</style>
组成:
-
头部标题
使用 vant 中 navBar 组件 传送门
说明:
- 不给
style
添加scoped
属性:样式可以直接作用到navBar
生成的结构中 - 但是一旦设置了
scoped
属性:样式无法作用到navBar
生成的结构中了 - 如果要让样式作用到生成的结构中:
- 1)可以去掉
scoped
- 2)可以给样式添加一个深度选择器:
/deep/
- 作用:让设置了
scoped
属性的样式作用到生成的结构中 - 注意点:
/deep/
必须配置less
语法来使用
- 作用:让设置了
- 1)可以去掉
- 不给
02-使用 iconfont
由于输入框之前有两个图标,在 vant 的图标库中没有这两个图标,为了解决这个问题 ,我们需要使用 iconfont 来加载这个图标
步骤:
- a. 生成 css 文件
- 1.0 打开 iconfont 的官网 传送门
- 2.0 去官网中找到自己要的图标 & 添加到购物车中
- 3.0 将我们需要的图标添加一个项目中
- 4.0 生成这个图标的 css 文件
- b. 在项目中使用 iconfont
- 1.0 复制生成的 css 代码
- 2.0 在项目中的
src/style
中创建一个index.css
并且将 css 代码粘贴到文件中 - 3.0 在
main.js
中导入这个文件 - 4.0 使用:
<i class="iconfont 图标的名称"></i>
,可以用插槽把图标替换进去
03- vant-form 中的验证属性
- 在van-form中的vant-file中要设置一个rules属性,当在vant-file中输入完内容之后要校验输入内容 是否输入是否合法
//输入手机号的那个filed输入框
:rules="[{required:true,message:'请输入手机号'},{pattern:/^1[3456789]\d{9}$/,message:'手机号不合法'}]"
//输入验证码的那个filed输入框
:rules="[{required:true,message:'请输入验证码'}]"
- 点击登录按钮之后要对整个form表单进行校验,登录按钮也要写在
<vant-form @submit="onSubmit"> </van-form>
中
一旦点击按钮会优先校验van-form中表单元素是否满足rules的规则,不满足提示错误信息,
满足就触发van-form中的submit,做一些校验成功之后要做的事情,发送请求
04 - 提交登录的参数
步骤:
- 1.0 在
onSubmit
方法中得到要提交的参数 - 2.0 将数据提交到服务器
- 下载 axios
- 导入 axios
- 请求接口提交数据:用户认证(登录注册)
- 接收返回的数据
- 跳转到首页
methods: {
// 点击登录按钮 校验成功之后要做的事情
async onSubmit () {
// 1.0发送请求
const res = await apiLogin(this.user)
console.log(res.data.data) // {token:xxx,refresh_token:xxx}
// 2.0登录成功保存token与refresh_token 到vuex跟localstorage中
this.$store.commit('setUserInfo', res.data.data)
setLocal('userInfo', res.data.data)
// 3.0登录成功跳转到首页
this.$router.push('/home')
}
}
05 - 封装 axios 请求文件
步骤:
- 1.0 在
utils
目录下创建一个文件myhttp.js
- 2.0 在文件中:
- 导入 axios
- 创建一个 axios 对象
- 设置拦截器
- 导出axios实例
// 封装axios
// 1.0 导入axios
import axios from 'axios'
// 2.0 创建axios的实例
const http = axios.create({
// 设置基地址
baseURL: 'http://ttapi.research.itcast.cn'
// xsrfCookieName:这个不要这个属性,否则会跨域错误,后台没设置
})
// 3.0 给axios添加请求拦截器
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
return config
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error)
})
// 添加响应拦截器
axios.interceptors.response.use(function (response) {
// 对响应数据做点什么
return response
}, function (error) {
// 对响应错误做点什么
return Promise.reject(error)
})
// 4.0 将http暴露给外界
export default http
06 - 封装网络请求文件
步骤:
- 1.0 在
api
目录下创建一个文件:use.js
- 2.0 在文件中
- 导入
myhttp.js
- 封装一个请求登录页面的接口
- 导入
- 3.0 在
login/index.vue
中使用这个方法
// 用来处理所有与用户相关的网络请求
// 导入自己封装好的axios实例
import http from '@/utils/myhttp'
// 1.封装登录的接口
function apiLogin (obj) {
return http({
method: 'post',
url: '/app/v1_0/authorizations',
data: obj
})
}
// 按需导出
export { apiLogin }
07 - async & await 的作用
问题:在开发过程中我们进行网络请求之后,需要将处理的结果放到回调函数中处理,这样子会响应代码阅读性。
为了解决这样的问题:在 es 的新版本标识中出了一个新的技术: async & await
作用:
- 将异步的代码以同步的方式进行书写
用法:
async
用来修饰异步代码所在的函数await
用来修饰异步代码- 使用
await
修饰后的异步代码可以同步的方式来接收返回结果
注意点:
- async & await 并没有改变代码:只是将代码的执行步骤进行了调整:
- 没有使用 async & await 之前:
- 遇到异步代码,会先执行同步代码,等待异步代码返回结果之后再执行
- 使用了 async & await 之后:
- 遇到 await 修饰后的代码,会等待这个异步代码返回结果,再执行后续的逻辑
- 没有使用 async & await 之前:
08- 保存登录信息到 vuex 中
步骤:
- 1.0 在
store
中 的state
下创建一个属性:userInfo
- 2.0 在
store
中的mutations
下创建一个方法:setUserInfo
- 在方法中给
userInfo
赋值
- 在方法中给
- 3.0 登录成功之后,应该直接将服务器返回的数据保存到
store
中的 `userInfo
// 2.0登录成功保存token与refresh_token 到vuex跟localstorage中
this.$store.commit('setUserInfo', res.data.data)
注意点:
- 仅仅只保存到 vuex 中,重新打开页面之后,数据会清空。我们还需要将数据保存到本地:
localstorage
中
import Vue from 'vue'
import Vuex from 'vuex'
// 导入存储数据到localStorage中的方法
import { getLocal } from '@/utils/mylocal'
Vue.use(Vuex)
export default new Vuex.Store({
state: { // 管理状态
// 在项目打开时应该从localStorage中取出来userInfo在vuex中
userInfo: getLocal('userInfo') || {}
},
mutations: { // 修改状态
// 定义一个setuserInfo的函数修改状态
setUserInfo (state, payload) {
// 给state里的userInfo赋值
state.userInfo = payload
}
}
})
09- 保存登录信息到 localstorage中
步骤:
-
1.0 在
onSubmit
方法中添加逻辑:- 登录成功之后,将登录成功后的信息保存到
localstorage
中
- 登录成功之后,将登录成功后的信息保存到
setLocal('userInfo', res.data.data)
-
2.0 在
store/index.js
中-
在
state
下面的userInfo
中添加代码:userInfo: getLocal('userInfo') || {} // 刷新数据vuex里的数据就没了,所以要在localStorage里面有数据的时候vuex也要有就把localStorage的数据拿出来就好 //下面这个是还没对localStorage进行操作方法的封装 //userInfo: JSON.parse(window.localStorage.getItem('userInfo')) || {}
-
10 - localstoreage 的操作方法封装
由于将来我们会频繁的对 localstroage 进行操作, 我们可以将操作的步骤封装为一些单独的方法放到一个单独的文件中
步骤:
- 1.0 在
utils
下添加一个文件mylocal.js
- 2.0 在
mylocal.js
文件中封装方法:- 存储数据的方法: localSet
- 取出数据的方法: localGet
- 删除数据的方法: localDel
- 3.0 将方法暴露出去
注意点:
- 取出数据 的方法中需要设置一个 `return
// 封装对所有localStorage的操作
// 封装一个存储数据到localStorage中的方法
const setLocal = (key, value) => {
window.localStorage.setItem(key, JSON.stringify(value))
}
// 封装一个从localStorage中获取数据的方法
const getLocal = (key) => {
return JSON.parse(window.localStorage.getItem(key))
}
// 封装一个从localStorage中 删除数据的方法
const removeLocal = (key) => {
window.localStorage.removeItem(key)
}
// 导出
export { setLocal, getLocal, removeLocal }
11- 给登录添加加载效果
登录时,网络可能比较慢,如果不作处理,用户会认为自己没有登录。会多次点击登录按钮。会额外的消耗服务器的性能。
任务:当用户点击一次登录之后,将登录按钮设置为加载状态。
准备知识点:
- 给按钮添加一个 loading 属性:
- 值为 true:按钮就会处于加载状态
- 值为 false:按钮就会处于可用状态
步骤:
- 1.0 给按钮添加一个
loading
属性 - 2.0 在
data
中设置一个isLoding
属性,默认值为false
- 3.0 当触发
onSubmit
时,将isLoading
改为true
- 4.0 当请求结束时,将
isLoading
改为false
- 5.0 在进入
onSubmit
时,判断isLoading
是否为false
,如果为false
才能发送请求
12 - try-catch的使用
由于黑马头条接口在登录失败时直接返回一个 400,400 会将浏览器直接报错,无法正常执行后续的代码。要解决这个问题,可以使用 try-catch 来捕获错误
try-catch 的用法:
try {
// 可以会出错的代码
} catch (error) {
// 如果出错,就执行 catch 中的代码,
// 如果不出错,就不执行 catch 中的代码
// error: 指的就是出错的信息
}
try-catch 的作用:
- 正常执行 try 中的逻辑:
- 如果没有问题就一直执行下去(不执行 catch 中的逻辑)
- 如果在 try 中的代码有错误,就会马上中断 try 中的逻辑去执行 catch 中的逻辑
methods: {
// 点击登录按钮 校验成功之后要做的事情
async onSubmit () {
// 进入是判断 isLoading是否为false,如果false说明目前还没有发送请求
if (this.isLoading === false) {
// 将加载状态设置为true
this.isLoading = true
try {
// 1.0发送请求
const res = await apiLogin(this.user)
this.isLoading = false
// console.log(res.data.data) // {token:xxx,refresh_token:xxx}
// 2.0登录成功保存token与refresh_token 到vuex跟localstorage中
this.$store.commit('setUserInfo', res.data.data)
setLocal('userInfo', res.data.data)
// 3.0登录成功跳转到首页
this.$router.push('/home')
} catch (error) {
console.log('出错了')
// 将loading动画不要
this.isLoading = false
// 添加一个失败的提示
this.$toast.fail('手机号或者验证码错误,请重新输入')
}
}
}
}
13 - 给登录失败添加提示框
vant 中的提示框是 toast
提示失败:
Toast.fail('失败文案');
注意点:
-
Toast 使用时与
element
中的message
是一样的- 如果在
.vue
文件中使用:this.$toast.fail('')
- 如果在其它的
.js
文件中使用:- 导入这个 Toast:
import { Toast } from 'vant'
- 使用这个 Toast:
Toast.fail('失败的文案')
- 导入这个 Toast:
- 如果在