场景:
移动端登录,需要短信验证码登录的使用场景
先贴一下做好的效果图:
(1)初始效果
(2)点击后效果
(3)计时结束后效果
需求:
在这个场景里用户需要输入手机号,然后点击“发送验证码”关键字,当收到短信验证码后,输入到接受验证码的控件中,然后点击登录。仔细想了想,这个“发送验证码”有点意思,可以封装成一个组件,那么日后就可以给别的小伙伴用啦。
因此,再来想想“发送验证码”应有的效果:
用户点击“发送验证码”,当手机号不正确或为空的时候,要提示用户修改手机号;当手机号正确时,向后台发送获取验证码的请求,与此同时修改显示效果:文字变为“xxs后重发”,颜色变为灰色,点击无效果。当倒计时结束后,文字颜色恢复,且内容变为“重新发送”。
技术:
因为要封装成一个组件,因此首先根据需求确定应该接收哪些数据,这里很简单,只需一个手机号作为要接收的数据,并且必须有手机号;其次是处理,当用户点击以后,调用方法进行处理,首先要判断手机号是否合理,并在不合理时给出提示,其次如果合理的话,就更改文字样式,并且发送请求。更改样式中涉及到倒计时,这里可以用setInterval
来解决。当检测到计时结束后,再次变更文字样式;在整个过程中不涉及到改变父组件里的数据操作。
解决方案:
分析2小时,代码10分钟,不要怕麻烦,理清流程才能减少日后调BUG的次数。话不多说,我们下面就简简单单,封装个小组件。
这是封装好的组件Loading:
<template>
<div :class="className" @click="requestSMS"><span> | </span>{{count}}{{message}}</div>
</template>
<script>
export default {
name: 'Loading',
props: {
// 用户电话
telNumber: {
required: true
}
},
data () {
return {
className: 'clickable',
message: '发送验证码',
count: '',
send: true,
timer: null,
reg: /^((13[0-9])|(14[5,7,9])|(15[^4])|(18[0-9])|(17[0,1,3,5,6,7,8]))\d{8}$/
}
},
methods: {
requestSMS () {
if (this.send) {
if (this.$props.telNumber === '' || this.$props.telNumber === undefined) {
this.$toast('请输手机号码')
} else if (!this.reg.test(this.$props.telNumber)) {
// 核对手机号格式
this.$toast('请输正确的手机号码')
} else {
this.send = false
// 请求短信验证码
console.log(this.$props.telNumber)
console.log('开始请求数据')
// 修改样式
this.className = 'unclickable'
this.message = 's后重发'
const TOTAL_TIME = 60
if (!this.timer) {
this.count = TOTAL_TIME
this.timer = setInterval(() => {
if (this.count > 0 && this.count <= TOTAL_TIME) {
this.count--
} else {
clearInterval(this.timer)
this.timer = null
this.count = ''
this.message = '重新发送'
this.className = 'clickable'
this.send = true
}
}, 1000)
}
}
}
}
}
}
</script>
<style scoped>
.clickable {
font-family: SourceHanSansCN-Normal;
font-size: x-small;
color: #5474C2;
letter-spacing: 0;
text-align: center;
}
.unclickable {
font-family: SourceHanSansCN-Normal;
font-size: x-small;
color: #B5BBC4;
letter-spacing: 0;
text-align: center;
}
span {
color: #B5BBC4;
margin-right: 3px;
}
</style>
在父组件中这样调用:
<Loading :telNumber="account" style="float:right"></Loading>
这个account
是在父组件中定义的一个数据,初始化为undefined
类型。