1.1 为什么要单独写一个js验证模块?
对于传统的表单验证或者一些其他的验证场景,我们只能老老实实的以一个一个编写对应的检测逻辑代码去检测一些数据是否符合规则。聪明的老哥们可能会把所有有关验证的方法或者函数都抽离到一个js文件中,但是 ,在每个需要验证的验证逻辑的js文件中我们还是需要把所有用到的检测方法导入进来,然后一遍又一遍的重写验证逻辑和验证流程…。这个过程不可谓不繁琐和无趣。
这个时候把所有验证逻辑和流程全部封装到一个模块中,我们只需要关注验证的结果而不需要关心验证过程从而达到关注点分离和代码的复用性,当然市面上也有很多UI框架提供了验证对象,但是毕竟和框架耦合在一起要是换一个框架怎么办?这个时候单独的一个验证模块的优势、便利性和必要性就展现出来了。
1.2 设计灵感
该验证模块在使用方式设计的时候借鉴了ThinkPHP的验证模块的内置规则规范和vue指令的结构。
1.3 github下载地址:checker
1.4 使用方式:
这里你大可不比关注一些语法细节,只需要关注使用的大概流程就行,具体语法细节那些在后面会做详细介绍。
1.4.1 通过<script>标签本地或者网络引入
<script src="xxx/checker.js"></script>
<script>
//要检测的数据对象
const data = {
name: 'mike',
age: 18,
hobby: '睡觉'
}
//rules一个包含一系列规则的数组
const rules = [{
name: 'name',//name对应data当中的字段名
rule: 'alphaDash|require|max:8' //rule对应的规则
}, {
name: 'age',
rule: 'between:10,20|require',
} {
name: 'hobby',
rule: 'in:吃饭,睡觉'
}];
const res = checker(data, rules);//返回一个检测资源对象
if (!res.result) {
//检测资源对象中有一个result属性表示检测的结构
console.error(res.errMsg) //检测资源对象中有一个errMsg属性表示发生错误的原因
} else {
console.log('验证通过');
}
</script>
1.4.2 使用ES6 Module导入
import checker from 'xxx/checker.js';
//要检测的数据对象
const data = {
name: 'mike',
age: 18,
hobby: '睡觉'
}
//rules一个包含一系列规则的数组
const rules = [{
name: 'name',//name对应data当中的字段名
rule: 'alphaDash|require|max:8' //rule对应的规则
}, {
name: 'age',
rule: 'between:10,20|require',
}, {
name: 'hobby',
rule: 'in:吃饭,睡觉'
}];
const res = checker(data, rules);//返回一个检测资源对象
if (!res.result) {
//检测资源对象中有一个result属性表示检测的结构
console.error(res.errMsg) //检测资源对象中有一个errMsg属性表示发生错误的原因
} else {
console.log('验证通过');
}
2.1 使用语法:
checker(data,rules,callback,returnType);
参数:
- data
- Object 、HTMLFormElement实例或者FormData实例 【必填】。
需要检测的数据对象只能是一个纯粹的对象 “{}”、一个form元素或者一个FormData的实例,如果传入一个其他类型则会抛出一个Error。
- Object 、HTMLFormElement实例或者FormData实例 【必填】。
- rules
Array 【必填】。
一个包含规则对象的数组,如果是一个空数组那么checker函数会立刻返回一个检测成功资源对象,而不会去进行任何检测。
rules数组中规则对象的结构规范:- name
String 该属性定义了该规则对象作用于data当中的字段名。【必填】
不要重复定义name相同规则对象,checker永远只会找数组当中最先定义的那一个。如果未定义name属性那么该规则对象则会被忽略,不会起作用。 - rule
String或者RegExp实例,如果为其他类型则抛出一个TypeError。【必填】
该属性定义了规则检测的具体行为,如果未定义name属性那么该规则对象则会被忽略,不会起作用。如果rule等于一个空字符串那么该规则也不会起作用,默认认为是检测成功。 - errMsg
String 【可选】
该属性定义了该规则检测失败时的错误信息,如果未定义该属性则采用内部失败的错误信息。
- name
- callback
Function 【可选】 。
每次检测完成一个字段之后会调用的回调函数,这个函数会接收一个检测资源对象作为参数。如果callback不是一个Function类型那么就会忽略它。 - returnType
String。【可选】。 可选值包括:[s、m、a],如果为其他值则默认为s,默认值为s。
s => single ,返回第一个检测失败或者所有字段均检测成功的资源对象,如果发生检测失败函数将立刻返回,后面的字段不会执行检测。
m => multiple, 返回所有检测失败字段资源对象数组【Array】,只包含检测失败的字段的资源对象,会等所有字段检测完成后返回。
a => all, 返回所有检测字段的资源对象数组【Array】,无论检测成功还是失败,会等所有字段检测完成后返回。
返回值:
- 一个resObj或者包含了多个resObj对象的数组,根据传入的returnType参数决定。
resObj对象结构:
- result ,一个Boolean值
表示验证结果,- errMsg,一个String
表示错误信息,result为true时为 “ok”,result为false时为检测失败的原因。- errField ,一个String
表示发生错误的字段名- errRule,一个String
表示验证失败的规则名
2.2 规则对象中的rule的语法
2.2.1 rule的结构:
- 一条规则可由一条或多条子规则构成,多条子规则之间通过字符中杠分割(|)。
- 一条子规则可由规则名+一个或多个修饰符+零个或者一个参数构成。
- 修饰符描述了子规则的行为偏好,修饰符必须处于参数标识符(:)或者(|)之前,子规则名之后。如果处于参数标识符(:)之后则会被解析器解析成参数。
- 处在参数修饰符(:)之后子规则分隔符(|)之前的均会被解析器解析成参数,参数字符串中不能出现(|),出现了则会当成子规则分隔符。。
- 多条子规则之间的解析顺序是从左到右的。所以检测结构也是从左到右层叠的。
- 参数中的区间语法, a,b,c,d,… | a,b | a 在一些需要用到区间的规则中会被解析。区间或者范围通过英文字符逗号分割(,),如果编写错误则会抛出一个TypeError。
const rule="子规则名.修饰符1.修饰2.修饰符n:参数|子规则2|子规则3";
2.2.2 内置修饰符表:
修饰符 | 作用 |
---|---|
.capital | 如果字段中存在英文字母那么必须全部大写 |
.lowercase | 如果字段中存在英文字母那么必须全部小写 |
.compose | 如果子规则为多种字符组合那么字段中每一种字符都必须存在至少一个 |
注意:修饰符均在指定规则下才能生效!
2.2.2.1 .capital示例
const data = {
name: 'mike'
};
const rules = [{
name: 'name',
rule: 'alpha.capital'//检测的字段如果存在字母则必须全部大写
}];
const res = checker(data, rules);
console.log(res);
下面是输出结果:
2.2.2.2 .lowercase示例
const data = {
name: 'Test'
};
const rules = [{
name: 'name',
rule: 'alpha.lowercase'
}];
const res = checker(data, rules);
console.log(res);
下面是输出结果:
2.2.2.3 .lowercase和.capital同时存在的情况下大小写字母都可以存在 示例
const data = {
name: 'Test'
};
const rules = [{
name: 'name',
rule: 'alpha.lowercase.capital'
}];
const res = checker(data, rules);
console.log(res);
下面是输出结果:
2.2.2.4 .compose示例
2.2.2.4.1 加.compose修饰符之前
name: 'Test'
};
const rules = [{
name: 'name',
//alphaDash:检测数字、字母、下划线、中横线组合,不能含有其他字符
rule: 'alphaDash'//默认情况下为包含关系,只要是数字、字母、下划线、中横线中的一种就行
}];
const res = checker(data, rules);
console.log(res);
2.2.2.4.2 加了.compose修饰符之后
const data = {
name: 'Test'
};
const rules = [{
name: 'name',
rule: 'alphaDash.compose'
}];
const res = checker(data, rules);
console.log(res);
2.2.2.4.3 加了.compose修饰符之后的正确写法
const data = {
name: 'Test1-' //同时存在了字母、数字和下划线或者中横线
};
const rules = [{
name: 'name',
rule: 'alphaDash.compose'
}];
const res = checker(data, rules);
console.log(res);
再次提醒:修饰符均在指定规则下才能生效!,在不支持的规则下使用会被忽略!
2.2.2.5 一条规则的解析流程图
2.2.3 内置子规则表:
子规则名 | 作用 | 参数 | 可用修饰符 |
---|---|---|---|
require | 必填项 | 无 | 无 |
number | 严格匹配数字(整数和小数)(不能含有任何其他非数字字符除了(-)) | 无 | 无 |
integer | 严格匹配整数(不能含有任何其他非数字字符除了(-)) | 无 | 无 |
float | 严格匹配小数(不能含有任何其他非数字字符除了(-)) | 无 | 无 |
boolean | 检测是否是一个布尔值 | 无 | 无 |
alpha | 检测英文字母,不能含有其他字符 | 无 | [.capital,.lowercase] |
alphaNum | 检测数字、字母组合,不能含有其他字符 | 无 | [.capital,.lowercase,.compose] |
alphaDash | 检测数字、字母、下划线、中横线组合,不能含有其他字符 | 无 | [.capital,.lowercase,.compose] |
chs | 检测汉字,不能含有其他字符 | 无 | 无 |
chsAlpha | 检测汉字、字母组合,不能含有其他字符 | 无 | [.capital,.lowercase,.compose] |
chsAlphaNum | 检测汉字、数字、字母组合,不能含有其他字符 | 无 | [.capital,.lowercase,.compose] |
chsDash | 检测汉字、数字、字母、下划线、中横线组合,不能含有其他字符 | 无 | [.capital,.lowercase,.compose] |
json | 检测是否是一个json字符串 | 无 | 无 |
检测是否是一个合法邮箱 | 无 | 无 | |
date | 检测是否是一个合法日期 | 无 | 无 |
url | 检测是否是一个合法URL | 无 | 无 |
ip | 检测是否是一个合法IP(ipv和ipv6) | 无 | 无 |
host | 检测是否是一个合法域名 | 无 | 无 |
idcard | 身份证号(15位、18位数字),最后一位是校验位,可能为数字或字符X | 无 | 无 |
telephone | 检测是否是一个合法座机电话(3-8)/(4-7) | 无 | 无 |
phone | 检测是否是一个合法手机号码 | 无 | 无 |
postcode | 检测是否是一个合法中国邮政编码 | 无 | 无 |
max | 检测字符串的最大长度 | integer | 无 |
min | 检测字符串的最小长度 | integer | 无 |
length | 检测字符串的是否等于某个长度或者长度是否在某个区间范围内 | integer or min,max | 无 |
in | 检测字段的值是否在某个范围之内 | a,b,c… | 无 |
notIn | 检测字段的值是否在不某个范围之内 | a,b,c… | 无 |
between | 检测字段的值是否在某个区间之内 | number1,number2 | 无 |
notBetween | 检测字段的值是否不在某个区间之内 | number1,number2 | 无 |
before | 检测字段的值是否在某个日期之前 | 一个合法日期 | 无 |
after | 检测字段的值是否在某个日期之后 | 一个合法日期 | 无 |
expire | 检测字段的值是否在某个日期范围之间 | date1,date2 | 无 |
notExpire | 检测字段的值是否不在某个日期范围之间 | date1,date2 | 无 |
file | 检测是否是一个文件或者类文件 | 无 | 无 |
fileSize | 检测文件的大小是否在指定区间范围之内 | size1,size2 or maxSize | 无 |
fileExt | 检测文件的后缀名是否在指定范围之内 | txt,png,jpg… | 无 |
fileMime | 检测文件的类型是否在指定范围之内 | text/plain,text/html… | 无 |
confirm | 检测该字段是否和另外一个字段的值一致 | String | 无 |
different | 检测该字段是否和另外一个字段的值不一致 | String | 无 |
eq,=,same | 检测该字段是否等于某个值 | string or number | 无 |
egt,>= | 检测该字段是否大于等于某个值 | number | 无 |
gt,> | 检测该字段是否大于某个值 | number | 无 |
elt,<= | 检测该字段是否小于等于某个值 | number | 无 |
lt,< | 检测该字段是否小于某个值 | number | 无 |
2.2.4 内置规则用法
2.2.4.1 格式验证类
require
验证某个字段必填,例如:
const data = {
name: