如果你受够了饿了么 ElementUI 原生的校验方式,那就来试试它吧! 项目地址
前言
饿了么 ElementUI 虽好,但表单校验的体验不够理想
如果说产品开发要讲究用户体验,那插件开发也要讲究开发体验,而好的开发体验,要靠好的 api 设计来保障
本人专注校验插件开发 30 年,有祖传的校验插件 api 设计(玩笑)。主要是参考了之前写的 vue-verify-pop 的 api,并加以完善,取其精华,去其糟粕,揉和日月之精华。。。
本插件只是对 ElementUI 原本的校验方式做了一层封装,核心的校验器仍然是 async-validator,非侵入式,完全不会影响你继续使用 ElementUI 的原生校验
注意:element 在 2.5.x 之后,对于使用了 v-model.number 的 el-input 将无法输入小数。
基于上面这个情况以及数字校验业务的综合考虑,自1.2.0
后,本插件数字相关的校验不再要求强数字类型,也就是说 “数字字符串” 也可以通过校验了(你无须再使用v-model.number
)。
当然了,你还是可以根据业务需要继续使用v-model.number
,不过需要将 el-input 的type
设置成 number 才能输入小数,坏处是如果输入了非 “数字字符串”,会在输入框有值的情况下触发校验插件的空提示。
安装
1 | npm install element-ui-verify |
使用
环境
vue版本:^2.3.0
element-ui版本:>=1.1.1
webpack模块环境
一,安装
1 | import Vue from 'vue' |
二,在 el-form-item 上配置校验规则
1 | <template> |
ok,你已经完成了一个内容为大于 0 的整数校验!(欢迎对比官方版的相似例子)
默认支持的校验规则
- length: 校验文本长度
- minLength: 校验文本最短长度
- gt: 校验数字要大于某数
- gte: 校验数字要大于等于某数
- lt: 校验数字要小于某数
- lte: 校验数字要小于等于某数
- maxDecimalLength: 校验数字最大小数位
- number: 校验是否为数字
- int: 校验是否为整数
- phone: 校验是否为手机号(随着号段的增加,未来可能需要更新)
- email: 校验是否为电子邮件地址
- verifyCode: 校验是否为 6 位数字验证码
配置
示例:
1 | Vue.use(elementUIVerify, { |
errorMessageTemplate
错误提示模板。默认值:默认模板
如要使用自定义模板,模板内容要覆盖 默认模板 中定义的所有字段,否则 getErrorMessage 在获取不到值的时候会抛异常
fieldChange
当绑定字段变化时,插件的默认行为。默认值:’verify’
注意:在输入框失去焦点时会始终触发校验
verify
当绑定字段变化时会实时触发校验
clear
当绑定字段变化时只清空校验结果,不触发校验
重要选项说明
verify
若要使用本插件,verify 选项是必须的,换句话说,如果没有配置该选项,那么你仍然可以正常使用 ElementUI 原生的校验
该选项还可以接收一个函数值,用于 自定义校验方法
canBeEmpty
插件默认开启输入内容不为空校验,如果开启该选项,一旦该输入项为空则会忽略该输入项之后所有的校验
该选项一般用于如下情况,比如邀请码这种一般可以为空,不为空又需要校验的输入项
1 | <!--当邀请码不为空时才校验长度是否等于6--> |
space
插件执行空检测时默认忽略空格,也就是说某个输入框中如果只输入了空格是过不了空检测的,除非设置该选项
1 | <el-form-item prop="test" verify space></el-form-item> |
emptyMessage
空检测错误提示
1 | <el-form-item prop="head" verify empty-message="请上传头像"></el-form-item> |
errorMessage
用于自定义校验不通过提示(空检测和自定义校验方法的错误提示不受该值影响)
1 | <el-form-item |
alias
懒人的福音,用于复用错误提示,默认值:”该输入项”。使用场景:
假设你的空检测错误提示模板为:
1 | {empty: '{alias}不能为空'} |
表单内容为:
1 | <el-form-item prop="unknown" verify></el-form-item> |
- 当
unknown
输入框为空时,会提示”该输入项不能为空”(alias 值默认为”该输入项”) - 当
姓名
输入框为空时,会提示”姓名不能为空”(显式设置了 alias 值时,提示内容自然会以该值去替换模板) - 当
地址
输入框为空时,会提示”地址不能为空”(大部分 el-form-item 都需要设置一个 label 项,而 label 项往往就代表该输入项的 alias,因此插件会取该值直接作为 alias,很贴心有木有)
fieldChange
参见全局 fieldChange 配置
watch
监听其他变量,触发自身校验
一个常见例子:密码一致性校验,pass1 的变化会触发 pass2 的校验(欢迎对比官方版的相似例子)
1 | <template> |
再举一个不适合使用该选项的场景,比如下面这个最少最多人数的例子,最少人数变化要触发最多人数的校验:
1 | <template> |
其实 watch 选项在这里完全没必要,因为插件会响应所有校验参数的变化来触发自身校验
,最多参与人数的gt
值引用了model.minNumber
,一旦model.minNumber
变化,就会触发校验
如果你再 watch 一下,反而会多触发一次。所以这样即可:
1 | <el-form-item |
注意事项
- 所有选项调用不能有大写字母,用中划线分隔,同 vue props 属性设置规则
length
minLength
gt
gte
lt
lte
maxDecimalLength
等需要接收数值的选项,该值须为数字(:length="1"
)verify
canBeEmpty
space
number
int
等无须接收值的选项一旦设置了,可以通过赋值为 undefined 来取消
规则简写
number,int,phone 等无须设定值的选项可以直接:
1 | <el-form-item prop="prop" verify number></el-form-item> |
gt
gte
lt
lte
maxDecimalLength
等数字规则无须再写 number
规则
1 | <!--该输入项内容必须为不大于10的数字--> |
全局 API
addRule (name: string | VerifyRulePropOptions, getter: RuleGetter): RuleGetter
用于 自定义校验规则
name
: 规则名称
本插件的校验选项基于 Vue 组件的 Prop,故该参数可以是一个类似 VueProp 的配置项:
1 | { |
这么做的好处是可以对规则接收值本身也做一些限制,提前规避一些不必要的调用错误,比如:
1 | <el-form-item prop="prop" verify length="哈哈哈"></el-form-item> |
上述这种情况,就很有可能使你的校验文本长度规则出现异常。当然了,如果你对调用者比较相信或者是那种无须接收值的规则,也可以省事点直接这样:
1 | import elementUIVerify from 'element-ui-verify' |
getter
: asyncValidatorRule 获取方法
该回调可以返回单条规则或规则数组,具体规则需要参见 async-validator
1 | // 单条 |
如果对上述示例中多条规则重复定义了type
有疑问的同学,可以看 这里
getRule (name: string): RuleGetter
用于获取校验规则。一般是和 自定义校验规则 搭配使用,方便已有规则的复用
返回内容即为 addRule 传入的getter
参数
getErrorMessage (name: string, templateData?: any): string
用于从通用错误提示模板中获取错误提示。一般是和 自定义校验规则 搭配使用
假设错误提示模板为
1 | { |
调用示例:
1 | import elementUIVerify from 'element-ui-verify' |
自定义校验方法
如果自带的校验规则满足不了你的需求,可以在校验规则中插入你自己的 校验方法
自定义校验方法在校验规则都通过后才会执行
1 | <template> |
自定义校验规则
和自定义校验方法的区别是这个适用于全局,等于增加插件自带的校验规则
前言已经说过,本插件的核心校验器来自 async-validator,故校验规则需要你先参考它的 文档
示例 1:新增一个校验是否为 10 位整数的规则
1 | import elementUIVerify from 'element-ui-verify' |
这样就完成了一个简单的规则拓展,你就可以在任何地方像使用默认规则那样来调用你的自定义规则,如下:
1 | <el-form-item prop="prop" verify int10></el-form-item> |
示例 2:新增一个校验是否为任意位整数的规则,与上面不同的是该规则需要接收一个规则参数
1 | import elementUIVerify from 'element-ui-verify' |
调用:
1 | <el-form-item prop="prop" verify :int-length="10"></el-form-item> |
看到这里,相信类似拓展一个支持正则校验的规则这种对你来说肯定不在话下了。更多示例你还可以直接翻看本插件 源码 中默认规则的添加
插件的默认校验不通过提示模版
1 | { |
常见问题
为什么不把 prop 配置项干掉?每次都要写校验规则都要写它好烦!
我也烦。但本插件是基于 ElementUI 的,所以很多地方会受到原始校验机制的限制,还要尽可能不对它产生影响。比如这个 prop 选项,如果把它干掉,会影响到 el-form 的校验,因为 ElementUI 以 prop 作为 uid 来存储校验队列
如何切换校验类型?比如某个输入框可能输入手机号也可能输入邮箱
1 | <el-form-item prop="prop" verify phone v-if="isPhone"></el-form-item> |
在规则变化不多的情况下也可以这样(该种方式切换类型时会立即触发校验)
1 | <el-form-item |
其他
在写gte
规则的时候,我首先引用了 async-validator 的数字类型规则,然后再引用了它的 Range 规则,
而它的 Range 规则同时支持字符串和数字,所以针对数字的校验需要显式再设置一遍type: number
,这虽然会导致gte
规则可能会校验两遍类型是否为数字,不过性能影响不大
1 | // 这里的min显然是要校验数字的 |
也不能算是 async-validator 的缺点吧,基于它当前的规则约定如果做规则推断的话收益不大,还会增加校验规则的不确定性,给调用者造成困惑。不过只针对本需求的话可以考虑把文本和数字的 range 规则给分开
这里可能你会问那为什么不直接用单条规则?
1 | {type: 'number', min: 3, errorMessage: 'xxxx'} |
如果这么写了,输入非数字的错误提示会是原始错误提示模板中的内容。为了不破坏 ElementUI 的原生校验(修改原始错误提示模板)和最大化复用 async-validator 内置的校验,只得通过拆分规则来让校验错误提示更具体
之后你在自定义校验规则的时候,如遇类似问题也可考虑通过规则拆分来让错误提示更具体
后话
由于本插件的校验选项是基于 VueProp,有如下缺点:
- 随着 ElementUI 的更新,未来有可能会和它的某些新增选项产生冲突
- 难以做到按照校验规则的书写顺序来执行校验,目前的大顺序是:空检测 > 通用规则 > 自定义校验方法。不过该条的影响不是很大,现有规则下的大部分场景不需要考虑规则顺序