文章目录
零.前置相关内容
1.Toast组件的使用
使用场景
在用户输入手机号后,需要给出提示,若输入正确:“发送成功,请注意查收!”,
若输入不正确:“请输入正确的手机号”
使用步骤
- Toast轻提示组件的注册安装,步骤略(同NavBar)
- 使用方式1----导入调用(组件或非组件内都可以):
Toast("提示内容")
- 使用方式2----通过this直接调用(组件内):
this.$toast("提示内容")
,
这种方法的本质是把方法注册挂载到了Vue原型上:Vue.prototype.$toast=xxx
常用用法
- 文字提示:Toast(‘提示内容’)
- 加载提示:
Toast.loading(){
message:'加载中',
forbidClick:true
}
- 成功/失败提示:Toast.success和Toast.fail
2.为什么要对axios进行二次封装?
省流
使用axios请求后端接口,一般都会对axios进行一些配置,比如配置基础地址,请求&响应拦截器等
所以在项目开发中,都会对axios进行基本的二次封装,单独封装到一个request模块中,便于维护使用
步骤(以获取图形验证码为例)
- 新建封装文件
utils/request.js
import axios from 'axios'
const instance = axios.create({// 创建一个axios实例instance
baseURL: 'http://smart-shop.itheima.net/index.php?s=/api', // 注意操作文档上的基础地址是否变动
timeout: 1000
})
// 请求拦截器:发送请求之前做些什么
instance.interceptors.request.use(config => {
return config// 成功的回调
}, error => {
return Promise.reject(error)// 失败的回调
})
// 响应拦截器:接收返回数据之前做些什么
instance.interceptors.response.use(res => {
return res.data// axios返回数据默认多包一层data,提前剥掉
}, err => {
return Promise.reject(err)
})
// 导出实例
export default instance
- 在页面中试调用(需提前查看阅读文档,
获取请求方式,请求路径和请求参数
)
import request from '@/utils/request.js'
data () {
return {
picUrl: '',
picKey: ''
}
},
async created () {
// const res = await request.get('/captcha/image')
//console.log('获取到的数据:', res)//获取到data,message,status三个属性
const { data: { base64, key } } = await request.get('/captcha/image') // 把需要的res对象解构出来
this.picUrl = base64
this.picKey = key
},
- 用获取到的数据动态渲染登录页面:
<div class="form-item">
<input type="text" class="inp" maxlength="5" placeholder="请输入图形验证码">
<!-- <img src="https://img0.baidu.com/it/u=1838409809,2846524470&fm=253&fmt=auto&app=138&f=JPEG?w=443&h=236"> -->
<img :src="picUrl">
</div>
3.为什么以及如何将请求封装成api接口?
在中大型项目中,最好把请求封装成方法,统一存放到api模块,与页面分离
这么做的理由是:
在上例中,若在页面中类似的请求多了起来,整个页面会充斥着请求的代码,可阅读性较差,而且相同的请求也没有被复用,更没有被统一管理
统一放到api模块后:
将实现请求和页面的分离,复用相同请求并对请求统一管理
步骤:(优化上例)
- 新建请求模块并封装:把之前在页面中发送的请求放在新文件
src/api/login.js
中封装起来
import request from "@/utils/request"
export const getPicCode=()=>{//起一个方法名,以与后面同页面的其他请求做区分
return request.get('/captcha/image');//必须要return,不然获取不到结果
}
- 在页面中
Login/index.js
按需导入并调用
import { getPicCode } from '@/api/login.js'
async created () {
const { data: { base64, key } } = await getPicCode()
this.picUrl = base64
this.picKey = key
},
}
- 优化:考虑到在created中将不止发送一次数据请求,可以把方法写在methods中然后再在created中调用
import { getPicCode } from '@/api/login.js'
created () {
this.getPicCodeMethods()
},
methods: {
async getPicCodeMethods () {
const { data: { base64, key } } = await getPicCode()
this.picUrl = base64
this.picKey = key
}
},
一.登录页静态布局
0.login页分为上下两部分
上面–导航条:使用vant的NavBar作为通用组件,(在几乎每个页面都使用)
下面–主题部分:自定义
1.NavBar组件的使用
- 在官网上查用法(属性和属性值)
- 在utils/vant-ui.js中按需引入
import { NavBar } from 'vant'
Vue.use( NavBar )
- 在Login页中使用
<van-nav-bar title="会员登录" left-arrow @click-left="$router.go(-1)" />
2.登录页主体部分
<template>
<div class="login">
<van-nav-bar title="会员登录" left-arrow @click-left="$router.go(-1)" />
<div class="container">
<div class="title">
<h3>手机号注册</h3>
<p>未注册的手机号登录后将自动注册</p>
</div>
<div class="form">
<div class="form-item">
<input type="text" class="inp" maxlength="11" placeholder="请输入手机号码">
</div>
<div class="form-item">
<input type="text" class="inp" maxlength="5" placeholder="请输入图形验证码">
<img src="https://img0.baidu.com/it/u=1838409809,2846524470&fm=253&fmt=auto&app=138&f=JPEG?w=443&h=236">
</div>
<div class="form-item">
<input type="text" class="inp" maxlength="5" placeholder="请输入短信验证码">
<button>获取验证码</button>
</div>
</div>
<div class="login-btn">登录</div>
</div>
</div>
</template>
效果:
二.图片验证码相关功能
图片验证码的本质是后台返回的照片,目的是强制人和机器之间的交互,抵御自动化攻击(如:避免批量请求获取短信)
1.获取图片验证码
2.对文本框输入的手机号码和图片验证码进行正则校验
//step1:分别在手机号和图形验证码的input框中,使用v-model双向绑定在data中声明的变量moblie和picCode
//step2:在函数isVaild中分别对两个变量进行正则校验,当它们格式错误时返回false
/*login/index.vue/methods*/
isValid () { // 正则校验:手机号和图形验证码
// 1.手机号的正则:以1开头,第2位3`9,一共11位数字
if (!/^1[3-9]\d{9}$/.test(this.mobile)) {
this.$toast('请输入正确的手机号!')
return false
}
// 2.图形验证码的正则:4个字符
if (!/^\w{4}/.test(this.picCode)) {
this.$toast('请输入正确的图形验证码!')
return false
}
// 其他情况则通过
return true
},
//step3:调用isValid函数
//在哪里调用?==>点击发送短信,或点击登录按钮时调用(后续内容)
三.短信验证码相关功能
1.实现倒计时效果:点击"获取验证码",开始倒计时59s
业务要求:
- 输入的手机号和图形验证码要正确
- 1分钟内倒计时只会触发一次
- 按钮的文字不是固定的,倒计时开始后变成"重新获取59s"
思路:
对"获取验证码"按钮绑定点击事件getCode,声明三个新变量totalSec,nowSec,timer,分别代表总秒数,当前秒数和定时器的名字
当前timer定时器并未开启,且总秒数=当前秒数时,开启定时器
让nowSec每秒自减,当它的值小于等于0时清空定时器并初始化变量
// 点击开启倒计时
getCode () {
if(!this.isVaild()) return//手机号和图形验证码格式不对,不继续往下了
if (!this.timer && this.totalSec === this.nowSec) {
this.$toast('短信发送成功,请注意查收!')
this.timer = setInterval(() => {// 1分钟内倒计时只会触发一次
console.log(this.nowSec--)
if (this.nowSec <= 0) {
clearInterval(this.timer)
this.timer = null
this.nowSec = this.totalSec
}
}, 1000)
}
优化:"获取验证码"按钮的文本从写死变成动态渲染
<button @click="getCode">{{this.nowSec==this.totalSec?'获取验证码':`重新获取${this.nowSec}`}}</button>
优化:为避免性能浪费,加入业务逻辑—当用户离开登录页时,关闭定时器
destroyed () {
clearInterval(this.timer)
}
2.获取短信验证码
- 查看接口文档,确定请求方式,请求路径,请求参数
- 封装请求
//api/login.js
......
//获取短信验证码
export const getMsgCode=(captchaCode, captchaKey, mobile)=>{
return request.post('/captcha/sendSmsCaptcha',{
form:{
captchaCode, //图形验证码
captchaKey, //图形验证码key
mobile //手机号
}
)
}
- 页面调用
import { getPicCode, getMsgCode } from '@/api/login.js'
...
methods:{
async getMsgCodeMethods(){//在getCode方法中调用
const res=await getMsgCode(this.picCode,this.picKey,this.mobile);
}
}
.