感谢:尤大大的 vue、有赞的 vant、async-validator、以及 asseek
链接:https://www.jianshu.com/p/d58fe749b97f
在下不才在 asseek 的基础上加入了一些自己的想法有了现在的版本。
抛砖引玉请多多提点。
修正内容:
-
Promise 代替 callback
-
添加 Proxy 实现校验的自动触发
-
精简部分代码以期降低阅读难度
目的:
自动校验、手动校验、校验错误信息展示
/*
* @Author: 吴占超
* @Date: 2018-11-20 15:16:16
* @Last Modified by: 吴占超
* @Last Modified time: 2018-11-21 21:43:11
* 校验扩展
* this.validator = new ValidatorUtils({
rules: this.rules,
data: this.formData })
this.formData = this.validator.Data
*/
import AsyncValidator from 'async-validator'
import _ from 'lodash'
export default class ValidatorUtils {
/**
* Creates an instance of ValidatorUtils.
* @param {Object} rules
* @param {Object} data
* @param {Object} errMsg 错误信息文本key 同data
* @param {Boolean} automatic 自动校验
*
* @memberOf ValidatorUtils
*/
constructor({ rules, data, errMsg = {}, automatic = true }) {
this.setRules(rules)
this.data = data
this.errMsg = errMsg
automatic && this.setProxyValidate()
}
// #region 属性
get Rules() {
return this.rules
}
set Data(value) {
this.data = value
}
get Data() {
return this.data
}
get Validators() {
return this.validators
}
set Validators(value) {
this.validators = value
}
set ErrMsg(value) {
this.errMsg = this.value
}
get ErrMsg() {
return this.errMsg
}
// #endregion
/**
* 自动校验代理设置
*
* @returns
*
* @memberOf ValidatorUtils
*/
setProxyValidate() {
let that = this
let p = {
set(target, key, value, receiver) {
target[key] = value
that
.validate(key)
.then(result => {})
.catch(() => {})
return true
}
}
this.data = new Proxy(this.data, p)
}
/**
* 设定规则
* @param rules rules object async-validator rules
* @param cover 是否替换旧规则
*/
setRules(rules, cover = true) {
!cover || (this.Validators = {})
_(rules)
.mapKeys(
(value, key) =>
(this.Validators[key] = new AsyncValidator({ [key]: value }))
)
.value()
}
/**
* 执行验证
*
* @param {String,Array} tempData 可选 传空将验证构造data 支持key,list<key>
* @returns Promise
*
* @memberOf ValidatorUtils
*/
validate(tempData) {
// 错误数组
const err = []
let that = this
_(this.Validators)
.keys()
.filter(
p =>
!tempData ||
(tempData &&
_(that.Data).hasIn(tempData) &&
((_.isString(tempData) && tempData === p) ||
(_.isArray(tempData) && _(tempData).hasIn(p))))
)
.value()
.forEach(p =>
this.Validators[p].validate({ [p]: this.Data[p] }, error => {
error && err.push(error[0])
this.setErrMsg(p, error)
})
)
if (err.length > 0) return Promise.reject(err)
else return Promise.resolve(tempData)
}
/**
*
* 设置error消息
* @param {any} error
*
* @memberOf ValidatorUtils
*/
setErrMsg(key, error) {
this.errMsg[key] = error ? error[0].message : undefined
}
}
规则声明:
<van-field :error-message="validator.ErrMsg.telNumber" v-model="formData.telNumber"
required clearable label="手机号"
icon="question" placeholder="请填写正确有效的手机号"
@click-icon="$toast('请填写正确有效的手机号')" />
data:()=>({
// 验证对象
validator: undefined,
// 表单数据源
formData: {
// 车牌号
carNumber: '鲁B',
// 手机号
telNumber: undefined
},
// 校验
rules: {
carNumber: [
{ required: true, message: '请输入鲁B/鲁U开头完整车牌号' },
{
validator: (rule, value, callBack) => {
/^[鲁]{1}[B|U]{1}[A-Z0-9]{5,6}$/.test(value) ? callBack() : callBack('请输入鲁B/鲁U开头完整车牌号')
}
}
],
telNumber: [
{
validator: (rule, value, callBack) => {
if (!value) {
callBack('请输入手机号码')
} else if (/^[1][0-9]{10}$/.test(value)) {
callBack()
} else {
callBack('请输入正确的手机号码')
}
}
}
]
},
......
}),
created() {
this.validator = new ValidatorUtils({
rules: this.rules,
data: this.formData })
this.formData = this.validator.Data
},