目录
validate 对整个表单进行校验的方法
- 参数为一个回调函数。该回调函数会在校验结束后被调用,并传入两个参数:是否校验成功(返回 boolean 类型)和未通过校验的字段(返回 object 类型)。若不传入回调函数,则会返回一个 promise
submitForm() {
this.$refs.form.validate(valid, object => {
if(valid){
// 当校验通过时,这里写逻辑代码
} else {
// 当校验不通过时,这里写逻辑代码
}
})
}
validator 验证器
- 可以为指定字段自定义验证函数 function(rule, value, callback)
validateField 对部分表单字段进行校验的方法
- 如发送短信验证码之前,校验手机号字段是否正确
sendVerifyCode() {
this.$refs.form.validateField('phone', (errorMessage) => {
if(!errorMessage){
// 当校验通过时,这里写逻辑代码;发送接口请求,验证码按钮进入倒计时状态
}
})
}
- 校验多个字段使用此方法,如校验手机号和密码字段是否正确
sendVerifyCode() {
this.$refs.form.validateField(['phone', 'pass'], (errorMessage) => {
if(!errorMessage){
// 当校验通过时,这里写逻辑代码;发送接口请求,验证码按钮进入倒计时状态
}
})
}
resetFields 对整个表单进行重置
- 将所有字段值重置为初始值并移除校验结果
手机验证码倒计时实现
- 使用间歇性计时器 setInterval,当时间为 0 时,清空计时器 clearInterval
表单注册案例代码
- 注:表单校验成功后,再去校验是否已阅读协议;如果已阅读发送接口请求,否则弹出错误提示
- 按钮上显示加载状态使用 :loading 属性
<template>
<section>
<el-form :model="form" label-width="100px" :rules="rules" ref="form" status-icon hide-required-asterisk>
<el-form-item label="手机号" prop="phone">
<el-input v-model.number="form.phone" ref="phone" placeholder="请输入手机号" />
</el-form-item>
<el-form-item label="短信验证码" prop="verifyCode">
<div style="display: flex;">
<el-input v-model.trim="form.verifyCode" ref="verifyCode" placeholder="短信验证码" />
<el-button type="primary" plain @click="sendVerifyCode" :loading="isLoading" style="margin-left: 10px;">{{btnText}}</el-button>
</div>
</el-form-item>
<el-form-item label="密码" prop="pass">
<el-input v-model.trim="form.pass" type="password" ref="pass" show-password placeholder="请输入长度为4-8位包含数字、字母、特殊字符的密码" />
</el-form-item>
<el-form-item label="确认密码" prop="checkPass">
<el-input v-model.trim="form.checkPass" type="password" ref="checkPass" show-password placeholder="确认密码" />
</el-form-item>
<el-form-item prop="isReading">
<el-checkbox v-model="form.isReading" ref="isReading">
我已阅读并同意<a href="" target="_blank">《服务协议》</a><a href="" target="_blank">《隐私条款》</a>
</el-checkbox>
</el-form-item>
<el-form-item>
<el-button @click="submitForm" type="primary">注册</el-button>
<el-button @click="resetForm">重置</el-button>
</el-form-item>
</el-form>
</section>
</template>
<script>
export default {
data(){
return{
form: {
phone: '', // 手机号
pass: '', // 第一次录入密码
checkPass: '', // 第二次录入密码
verifyCode: '', // 验证码
isReading: false, // 协议是否阅读
},
btnText: '短信验证码', // 短信验证码按钮文字
time: 6, // 短信验证码时间
isLoading: false, // 短信验证码按钮是否显示加载中
rules: {
phone: [{required: true, validator: this.validatePhone, trigger: 'blur'}],
pass: [{required: true, validator: this.validatePass, trigger: 'blur'}],
checkPass: [{required: true, validator: this.validatePass2, trigger: 'blur'}],
verifyCode: [{required: true, message: '请输入验证码', trigger: 'blur'}],
}
}
},
methods: {
submitForm(){
this.$refs.form.validate((valid, object) => {
if(valid){
if(this.form.isReading){
console.log('submit Form')
// 逻辑处理发送接口请求
} else {
this.$message.error('请阅读并同意相关协议')
}
} else {
for(let key in object){
let dom = this.$refs[key] // 自动定位到校验失败的位置
// 滚动到指定节点
dom.$el.scrollIntoView({
block: 'center', // 值有 start、center、end、nearest;当前显示在视图区域中间
behavior: 'smooth' // 值有 auto、instant、smooth;缓动动画(当前是慢速的),instant(瞬间)
})
}
console.log('error submit')
return false
}
})
},
resetForm(){
this.$refs.form.resetFields() // 重置表单
},
validatePhone(rule, value, callback){
if(value === ''){
callback('请输入手机号')
} else {
const reg = /^((1[3,5,8][0-9])|(14[5,7])|(17[0,5,6,7,8])|(19[7]))\d{8}$/
if(reg.test(value)){
callback()
} else {
callback('请输入正确的手机号')
}
}
},
validatePass(rule, value, callback){
if(value === ''){
callback('请输入长度为4-8位包含数字、字母、特殊字符的密码')
} else {
const reg = /^(?=.*\d)(?=.*[a-zA-Z])(?=.*[\W_]).{4,8}$/
if(reg.test(value)){
callback()
} else {
callback('请输入长度为4-8位包含数字、字母、特殊字符的密码')
}
}
},
validatePass2(rule, value, callback){
if(value === ''){
callback('请再次输入密码')
} else if(value !== this.form.pass) {
callback('两次输入密码不一致!')
} else {
callback()
}
},
sendVerifyCode(){
/** validateField 对部分表单字段进行校验的方法 */
this.$refs.form.validateField('phone', errorMessage => {
if(!errorMessage){
// 发送接口请求后按钮进入倒计时状态
/**
* 时间开始倒数
* 按钮进入禁用状态
* 如果倒计时结束 按钮恢复可用状态 按钮文字变成重新发送 把倒计时时间重置
* 倒计时的过程中 按钮文字显示为 多少s后重新发送
*/
let timer = setInterval(() => {
this.time-- // 时间进入倒计时
this.btnText = `${this.time}s后重新发送`
this.isLoading = true // 按钮显示加载中
console.log(this.time)
if(this.time === 0){
this.btnText = '重新发送'
this.time = 6 // 重置时间
this.isLoading = false // 重置加载按钮
clearInterval(timer)
}
}, 1000)
}
})
}
}
}
</script>
<style scoped>
a{
text-decoration: none;
color:#409EFF;
}
</style>
表单注册案例代码优化
- 注意:此处 dom 节点是一个数组
<template>
<section>
<!-- flexLayout 指的是输入框 + 按钮布局 -->
<el-form :model="form" label-width="100px" :rules="rules" ref="form" status-icon hide-required-asterisk>
<el-form-item v-for="(item, index) in formList" :key="index" :label="item.label" :prop="item.prop">
<el-input
v-if="item.type === 'number'"
v-model.number="form[item.prop]"
:ref="item.prop"
:placeholder="item.placeholder"
/>
<div v-if="item.type === 'flexLayout'" style="display: flex;">
<el-input
v-model.trim="form[item.prop]"
:ref="item.prop"
:placeholder="item.placeholder"
/>
<el-button
type="primary"
plain
style="margin-left: 10px;"
@click="sendVerifyCode(item.prop)"
:loading="isLoading"
:disabled="isDisabled"
>{{btnText}}</el-button>
</div>
<el-input
v-if="item.type == ('text' && 'textarea' && 'password')"
v-model.trim="form[item.prop]"
:ref="item.prop"
:placeholder="item.placeholder"
:show-password="item.showPassword"
:type="item.type === 'password' ? 'password' : 'text' || 'textarea'"
/>
<el-checkbox v-if="item.type === 'checkbox'" v-model="form[item.prop]" :ref="item.prop">
我已阅读并同意<a href="" target="_blank">《服务协议》</a><a href="" target="_blank">《隐私条款》</a>
</el-checkbox>
</el-form-item>
<el-form-item>
<el-button @click="submitForm" type="primary">注册</el-button>
<el-button @click="resetForm">重置</el-button>
</el-form-item>
</el-form>
</section>
</template>
<script>
export default {
data(){
return{
formList: [
{label: '手机号', prop: 'phone', type: 'number', placeholder: '请输入手机号'},
{label: '短信验证码', prop: 'verifyCode', type: 'flexLayout', placeholder: '请输入短信验证码'},
{label: '密码', prop: 'pass', type: 'password', showPassword: true, placeholder: '请输入长度为4-8位包含数字、字母、特殊字符的密码'},
{label: '确认密码', prop: 'checkPass', type: 'password', showPassword: true, placeholder: '确认密码'},
{label: '', prop: 'isReading', type: 'checkbox', placeholder: ''},
],
form: {
phone: '', // 手机号
verifyCode: '', // 验证码
pass: '', // 第一次录入密码
checkPass: '', // 第二次录入密码
isReading: false, // 协议是否阅读
},
btnText: '短信验证码', // 短信验证码按钮文字
time: 10, // 短信验证码时间
isLoading: false, // 短信验证码按钮是否显示加载中
isDisabled: false, // 短信验证码按钮是否禁用
rules: {
phone: [{required: true, validator: this.validatePhone, trigger: 'blur'}],
pass: [{required: true, validator: this.validatePass, trigger: 'blur'}],
checkPass: [{required: true, validator: this.validatePass2, trigger: 'blur'}],
verifyCode: [{required: true, message: '请输入验证码', trigger: 'blur'}],
}
}
},
methods: {
submitForm(){
this.$refs.form.validate((valid, object) => {
if(valid){
if(this.form.isReading){
console.log('submit Form')
// 逻辑处理发送接口请求
} else {
this.$message.error('请阅读并同意相关协议')
}
} else {
for(let key in object){
let dom = this.$refs[key] // 自动定位到校验失败的位置
/** 注意此处 dom 节点是一个数组 */
console.log(key, dom, dom[0].$el)
// 滚动到指定节点
dom[0].$el.scrollIntoView({
block: 'center', // 值有 start、center、end、nearest;当前显示在视图区域中间
behavior: 'smooth' // 值有 auto、instant、smooth;缓动动画(当前是慢速的),instant(瞬间)
})
}
console.log('error submit')
return false
}
})
},
resetForm(){
this.$refs.form.resetFields() // 重置表单
},
validatePhone(rule, value, callback){
if(value === ''){
callback('请输入手机号')
} else {
const reg = /^((1[3,5,8][0-9])|(14[5,7])|(17[0,5,6,7,8])|(19[7]))\d{8}$/
if(reg.test(value)){
callback()
} else {
callback('请输入正确的手机号')
}
}
},
validatePass(rule, value, callback){
if(value === ''){
callback('请输入长度为4-8位包含数字、字母、特殊字符的密码')
} else {
const reg = /^(?=.*\d)(?=.*[a-zA-Z])(?=.*[\W_]).{4,8}$/
if(reg.test(value)){
callback()
} else {
callback('请输入长度为4-8位包含数字、字母、特殊字符的密码')
}
}
},
validatePass2(rule, value, callback){
if(value === ''){
callback('请再次输入密码')
} else if(value !== this.form.pass) {
callback('两次输入密码不一致!')
} else {
callback()
}
},
sendVerifyCode(){
/** validateField 对部分表单字段进行校验的方法 */
this.$refs.form.validateField('phone', errorMessage => {
if(!errorMessage){
// 发送接口请求后按钮进入倒计时状态
/**
* 时间开始倒数
* 按钮进入禁用状态
* 如果倒计时结束 按钮恢复可用状态 按钮文字变成重新发送 把倒计时时间重置
* 倒计时的过程中 按钮文字显示为 多少s后重新发送
*/
let timer = setInterval(() => {
this.time-- // 时间进入倒计时
this.btnText = `${this.time}s后重新发送`
this.isLoading = true // 按钮显示加载中
this.isDisabled = true // 按钮禁用
console.log(this.time)
if(this.time === 0){
this.btnText = '重新发送'
this.time = 10 // 重置时间
this.isLoading = false // 重置加载按钮
this.isDisabled = false // 重置按钮
clearInterval(timer)
}
}, 1000)
}
})
}
}
}
</script>
<style scoped>
a{
text-decoration: none;
color:#409EFF;
}
</style>