vue表单验证插件

表单验证

vue插件也可以用来注入全局变量.比如用户基本信息, 一些公共数据, 公告方法.

表单验证的两种方式:

1. 基于标签(html): 把验证逻辑放在html标签内, 优点是更清晰。自定义指令实现。
2. 基于model: 把验证逻辑放在js, 优点是更容易实现, 更易定制化。插件实现。

(挖坑: 用自定义指令实现一个类似的)

实现: 实现一个小型表单验证插件

  1. 先复习插件的关键点: 使用(注入/在实例中使用)/定义(install/mixin/钩子函数)
  2. 表单验证的流程
    • 设置验证函数, 配置错误信息
    • 遍历执行验证函数, 返回整体验证结果和错误信息
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
<template>
<div id="app">
<form @submit="validate">
<input v-model="text">
<br>
<input v-model="email">

<ul v-if="!$v.valid" style="color:red">
<li v-for="error in $v.errors">
{{ error }}
</li>
</ul>

<input type="submit" :disabled="!$v.valid">
</form>
</div>
</template>
<script>
const validationPlugin = {
// Implement this!
install(Vue) { // 和mixin不一样的是, 这个install的第一个参数是触发vue.use的Vue实例
Vue.mixin({
beforeCreate() { // 我不知道 为什么要在这个钩子函数?Created不行吗
// 获取到实例上的 validations
const rules = this.$options.validations

if(rules) {
// 把验证的对象$v挂载到computed钩子函数上
this.$options.computed =
Object.assign({}, this.$options.computed, {
$v () {
// 初始化验证结果与错误信息
let valid = true
const errors = []

// 遍历rules, 对每个rule进行验证
// 这里要说一点, 我们并没从dom结构上去取值, 我们是直接从state上取, 因为在data里有 text/email
// 所有我们需要的value
Object.keys(rules).map(key => {
const rule = rules[key]
// 注意:我们在data中初始化了这个值,这意味着我们在这里触发了getter, 进行了依赖收集
// 接下来每次触发setter都会执行一次
const value = this[key]

// 把value传入在validations上对应的验证函数
const result = rule.validate(value)
// 如果错误了就触发validations上对应的message函数
if(!result) {
valid = false
errors.push(rule.message(key, value))
}
})

return { // 最后,返回验证结果和队列
valid,
errors
}
}
})
}
},
})
}
}

Vue.use(validationPlugin)

const emailRE = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/

new Vue({
el: '#app',
data: {
text: 'foo',
email: ''
},
validations: {
text: {
validate: value => value.length >= 5,
message: (key, value) => `${key} should have a min length of 5, but got ${value.length}`
},
email: {
validate: value => emailRE.test(value),
message: key => `${key} must be a valid email`
}
},
methods: {
validate (e) {
if (!this.$v.valid) {
e.preventDefault()
alert('not valid!')
}
}
}
})
</script>