本文使用 es6、不依赖任何第三方库实现一个简单的表单验证插件 github
效果
1
2
3
4
5
| <div class="form_group tel">
<label for="name">手机</label>
<input type="tel" name="tel" id="tel">
<p class="message"></p>
</div>
|
1
2
3
4
5
6
7
8
| // 配置
{
target: '#tel', // 验证目标
message: { target: '.tel p', success: '手机格式正确' }, // 验证信息显示的地方
validators: [ // 验证规则数组
{ name: 'tel', args: { message: '手机格式错误' } }
]
}
|
代码结构
- 验证插件分为
验证类Validator
,和 验证规则validators
验证类Validator
: 为主逻辑,负责接受表单的配置并对表单执行相应的验证规则。
验证规则validators
: 其内封装了大量的验证规则,供表单选用。
每个验证规则有着相同的结构,它们接收 表单的 value 返回验证结果和报错信息。例子如下:
1
2
3
4
5
6
| // 针对手机号的验证规则
const tel = (str='', {message=''}={}) =>
({
status: /^1[3|4|5|7|8][0-9]{9}$/.test(str), // 验证状态
message // 报错信息
})
|
验证类 Validator
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| class Validator {
// 接受配置 validatorConfig: 验证器配置, targetConfig: 针对于表单的配置
/*
* validatorConfig {}
* - error 每个表单验证失败时的函数 Function
* - success 每个表单验证成功时的函数 Function
* - reset 对表单执行重置操作时的函数 Function
* targetConfig [{}, {}, ...] -> 各个表单的配置
* - target 验证目标的选择器 String(Selector)
* - message 验证信息的配置 Object
* - target 验证信息显示位置的选择器 String(Selector)
* - placeholder 验证信息的默认值,重置时会显示该文本 String
* - success 验证成功时会显示该文本 String
* - validators 验证规则的配置 [{}, {}, ...] -> 各个验证规则的配置
* - name 验证规则的名字 (validators[key]) String
* - args 验证规则的配置参数 Object
* - message 必有 该规则验证失败的显示文本 String
* - ... 该验证规则的其他配置参数 Any (各验证规则不同)
*/
constructor (config) {}
// 验证主逻辑
_check () {}
// 单个表单的验证 (只对单个表单执行 _check)
run () {}
// 执行全部表单的验证 (对所有要验证的表单执行 _check)
runAll () {}
// 重置表单为初始状态
reset () {}
}
|
验证主逻辑 _check
其接受 验证表单的配置,并执行相应验证逻辑
如接受了以下配置:
1
2
3
4
5
6
7
8
| {
target: '#tel', // 验证目标
// 验证信息显示的地方
message: { target: '.tel p', success: '手机格式正确' },
validators: [ // 验证规则数组
{ name: 'tel', args: { message: '手机格式错误' } }
]
}
|
需实现功能如下:
- 对目标表单(target)执行配置中指定的验证规则 (validators: 此次配置中只有一个验证规则)
- 如验证规则中有 required ,则说明该表单为必填项,必须进行表单验证。
- 如验证规则中无 required ,则说明该表单为选填项,只在有输入时才进行表单验证。(该例配置为选填)
- 当验证成功时需在 message.target 处显示 message.success 的文本。
- 当验证失败时需在 message.target 处显示 验证规则中的指定 的文本。
- 失败文本显示优先级同验证规则配置的先后顺序。
以下是具体实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
| _check (config) {
const
validatorCfg = this._validatorConfig, // 验证器配置
$target = $(config.target), // 验证的表单
val = $target.value, // 验证的 value
$message = $(config.message.target), // 验证信息显示的地方
ownValidators = config.validators, // 所有验证规则
result = [] // 失败信息数组
let required = false // 不是必填项的话,只在有输入内容时进行检查 (默认为不必填)
// 遍历执行验证器
ownValidators.forEach(validator => {
if (validator.name == 'required') required = true // 必填
const temp = Validators[validator.name](val, validator.args) // 执行验证器
// 如验证失败,则存储失败信息
if ( ! temp.status) result.push( temp.message )
})
if ( ! required && val.length === 0) return // 可跳过检验
if (result.length > 0) { // 有错误信息
validatorCfg.error && validatorCfg.error($target) // 失败回调
$message.textContent = result[0]
}
else { // 验证通过
validatorCfg.success && validatorCfg.success($target) // 成功回调
$message.textContent = config.message.success || ''
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| // 单个验证 需传入要验证 input 的 id
run (target) {
// 得到当前要验证的表单的配置
const curConfig = this._targetConfig.filter(config => config.target === `#${target}`)[0]
this._check(curConfig)
}
// 执行全局验证
runAll () {
this._targetConfig.forEach(this._check.bind(this))
}
// 重置表单
reset () {
this._targetConfig.forEach(config => {
const
$target = $(config.target),
$message = $(config.message.target)
$target.value = ''
$message.textContent = config.message.placeholder || ''
})
this._validatorConfig.reset( this._allTarget ) // 重置回调
}
|
自此我们的验证插件就写完了,可自行在 validators 中编写更多的验证规则
继续优化
- 提交表单时应需得到所有表单的验证状态,全通过则提交。
- 目前失败信息提示过于单一。
- 如表单验证中需与后台通信(如验证用户名是否注册),那么验证器应该支持异步的验证规则。
- 目前会执行所有验证规则,可选择在验证规则失败时,就不再往下继续验证了,以提高性能。