日常开发需要对表单内容格式进行逐项校验,校验不通过时提示校验信息,写了个表单验证组件,适用于小程序开发和vue开发。
validate.js
// validate.js
// 验证手机号
export function checkPhone(value) {
return /^1\d{10}$/.test(value)
}
export class Validator {
constructor(validators, caller) {
this.validators = validators;
this.caller = caller || this;
}
// 单项表单规则校验
validate(key, value) {
const rule = this.validators[key];
if (!rule) {
return {
bool: true
}
}
for (let i = 0; i < rule.validators.length; i++) {
const r = rule.validators[i];
if (!r.validator.call(this.caller, value)) {
this.validators[key].errTips = r.tips;
return {
bool: false,
errTips: r.tips
};
}
}
this.validators[key].errTips = '';
return {
bool: true
};
}
// 表单验证
validateRules(form, showToast = true) {
const utils = getApp().utils;
let result = true;
for (const key in form) {
const res = this.validate(key, form[key]);
if (!res.bool) {
result = false;
showToast && utils.msg(res.errTips);
break;
}
}
return result;
}
}
使用:
import {
Validator,
checkPhone
} from 'validate'
Page({
data: {
needPhone: false,
form: {
phone: '15611111111', // 手机号码
// ... 其它表单字段
},
formRules: {
phone: {
validators: [
{
tips: '请输入手机号码',
validator: function(val) {
// 如果需要手机号,则需要校验非空
// Validator劫持了page对象,才可以在校验函数内引用this
// 验证返回false时提示错误信息
if(this.data.needPhone) {
return !!val
}
return true
}
},
{
tips: '请输入正确的手机号码',
validator: checkPhone
}
]
},
}
},
onLoad() {
setTimeout(() => {
console.log('submit')
this.submit()
}, 1000)
},
submit() {
let validator = new Validator(this.data.formRules, this)
let form = this.data.form
let result = validator.validateRules(form)
console.log(result)
// 输出表单验证结果,返回true表示表单校验全部通过
}
})
这里稍微难理解一点的就是Validator.validate方法内用到了call方法,为啥要这样写呢?因为formRules在data中定义,如果里面的校验函数想要比较方便地访问this.data的数据,我们在创建Validator对象时把Page的实例传入到Validator实例中,然后在执行校验的时候就可以用formRules中的validator劫持Page的实例,validator就可以在Page环境中访问到this.data的数据啦!