使用 vue 和 element-ui 开发的前端工程,进行资源创建时,需要在前端页面对表单进行校验,特此记录,以备后需。
普通输入框的校验,可以直接使用默认的校验器进行校验,示例如下:
1)对数据模型添加 rules 规则
<template>
<div class="app-container">
<el-dialog
:visible.sync="dialogFormVisible"
:title="$t('business.businessApplicationMonitor')"
:show-close="false"
:close-on-click-modal="false"
:close-on-press-escape="false"
width="620px">
<el-form ref="businessForm" :model="temp" :rules="businessVerifyRules" label-width="120px" label-position="left">
<el-form-item :label="$t('business.regionName')" prop="region_name">
<el-select v-model="temp.region_name" :placeholder="$t('business.placeholder')">
<el-option v-for="region in regions" :key="region.value" :label="region.label" :value="region.value"></el-option>
</el-select>
</el-form-item>
<el-form-item :label="$t('business.name')" prop="name">
<el-input v-model="temp.name" :clearable="true" style="width: 400px"/>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="onCancel"> {{ $t('business.cancel') }} </el-button>
<el-button type="primary" @click="onSubmit"> {{ $t('business.confirm') }} </el-button>
</div>
</el-dialog>
</div>
</template>
:rules="businessVerifyRules"
为该表单添加验证规则,每一个表单项的 prop 属性将作为表单校验的属性名称,需要指定。
2)编写 rules 规则
export default {
name: 'Business',
data() {
return {
businessVerifyRules: {
region_name: [{
required: true, trigger: ['blur', 'change'], message: this.$t('confirm.nullWarning')
}],
name: [{
required: true, trigger: 'blur', message: this.$t('confirm.nullWarning')
}]
}
};
}
在数据部分编写校验规则,name,port等表示被校验属性,需要和表单项中的 prop 属性指定的属性名称保持一致,否则无法完成校验功能。
其内置的校验器类型还包括:
- string:必须是字符串类型,这也是默认的类型。
- number:必须是数值类型。
- boolean:必须是布尔类型。
- method:必须是函数类型。
- regexp: 必须是 RegExp 的实例或者一个可以无异常地创建 RegExp 实例的字符串。
- integer:必须是数值类型和整数。
- float:必须是数值类型和一个浮点数。
- array:必须是由 Array.isArray 确定的数组。
- object:必须是一个对象类型,并且不是 Array.isArray。
- enum:值必须存在于 enum 中。
- date:值必须由 Date 确定有效。
- url:必须是一个 url 类型。
- hex:必须是一个 hex 类型。
- email:必须是一个 email 类型。
对于数值类型的校验,可以使用默认的 number
类型校验,但是我们的数值在业务逻辑上有其特殊性,其实是个端口号,所以就有以下要求:
- 用户必须输入数值,不能提交空字符串。
- 用户的输入必须是可解析为数值的字符串,不能是其他的字符串。
- 用户输入的数值必须在 1024~65535 之间,不能超出这个范围。
为了同时满足以上要求,我们可以编写自定义的校验函数,将校验逻辑写在校验函数中,校验通过则放行,不通过则返回明确的错误提示。
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
|
<template>
<div class="app-container">
<el-dialog
:visible.sync="dialogFormVisible"
:title="$t('business.businessApplicationMonitor')"
:show-close="false"
:close-on-click-modal="false"
:close-on-press-escape="false"
width="620px">
<el-form ref="businessForm" :model="temp" :rules="businessVerifyRules" label-width="80px">
<el-form-item :label="$t('business.port')" prop="port">
<el-input v-model="temp.port" :clearable="true" style="width: 400px"/>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="onCancel"> {{ $t('business.cancel') }}</el-button>
<el-button type="primary" @click="onSubmit"> {{ $t('business.confirm') }}</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
name: 'Business',
data() {
const validatePort = (rule, value, callback) => {
this.$refs['businessForm'].clearValidate();
if (value) {
const port = parseInt(value);
// 判断是否为数字
if (isNaN(port)) {
return callback(new Error(this.$t('business.validateNumber')));
}
if (port <= 1024 || port > 65535) {
return callback(new Error(this.$t('business.validateRange')));
}
return callback();
} else {
return callback(new Error(this.$t('business.nullWarning')));
}
};
return {
businesses: [],
temp: {
id: 0,
gid: 0,
name: '',
prome_id: 0,
labels: [],
port: 10106
},
businessVerifyRules: {
port: [{
required: true, trigger: 'blur', message: this.$t('confirm.nullWarning')
}, {
validator: validatePort, trigger: 'blur'
}]
}
};
}
}
</script>
|
在 businessVerifyRules 中添加自定义校验器
1
2
3
4
5
|
businessVerifyRules: {
port: [{
validator: validatePort, trigger: 'blur'
}]
}
|
通过 validator 字段指定自定义校验函数 validatePort,触发条件为:blur。
对于复杂数据结构的校验,采取的方式是编写自定义的校验函数,将校验逻辑封装到校验函数中,校验通过则放行,不通过则返回错误提示,但是需要注意的是,每次执行校验函数时,需要先清除上次的校验结果,否则校验效果就比较滑稽了。
比如我们的项目中,需要校验键值对,采用了如下的方式:
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
|
<template>
<div class="app-container">
<el-dialog
:visible.sync="dialogFormVisible"
:title="$t('business.businessApplicationMonitor')"
:show-close="false"
:close-on-click-modal="false"
:close-on-press-escape="false"
width="620px">
<el-form ref="businessForm" :model="temp" :rules="businessVerifyRules" label-width="80px">
<el-form-item :label="$t('business.label')" prop="label">
<span>
<el-input value="" style="width: 400px" type="hidden"/>
</span>
</el-form-item>
<el-form-item
v-for="(label, index) in temp.labels"
:key="'label' + index"
prop="labels">
<span>
<el-input v-model="label.key" :clearable="true" style="width: 199px"></el-input>
<el-input v-model="label.value" :clearable="true" style="width: 199px"></el-input>
<el-button
v-if="temp.labels.length !== 1"
type="danger"
size="mini"
icon="el-icon-delete"
circle
@click.prevent="removeLabel(index)"/>
<el-button
v-if="index === temp.labels.length - 1"
type="primary"
size="mini"
icon="el-icon-plus"
circle
@click.prevent="addLabel"/>
</span>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="onCancel"> {{ $t('business.cancel') }}</el-button>
<el-button type="primary" @click="onSubmit"> {{ $t('business.confirm') }}</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
name: 'Business',
data() {
const validateLabels = (rule, value, callback) => {
this.$refs['businessForm'].clearValidate();
if (value) {
if (value.length > 0) {
for (let i = 0; i < value.length; i++) {
if (value[i].key === '' || value[i].value === '') {
return callback(new Error(this.$t('business.validateLabel')));
}
}
return callback();
} else {
return callback(new Error(this.$t('business.nullWarning')));
}
} else {
return callback(new Error(this.$t('business.nullWarning')));
}
};
return {
businesses: [],
temp: {
id: 0,
gid: 0,
name: '',
prome_id: 0,
labels: [],
port: 10106
},
label: {
key: '',
value: ''
},
businessVerifyRules: {
labels: [{
validator: validateLabels, trigger: ['blur', 'change']
}]
}
};
}
}
</script>
|
弹出框中是一个表单,表单中有个标签项,每项均是键值对,需要每项同时都配置键值对,如果没有同时配置,需要在页面给出提示,可以在并列显示的标签后面点击按钮删除当前标签。我们将校验逻辑写在自定义校验函数中,然后加入到校验规则里,就可以起作用了。
需要注意的是,每次校验前,需要使用表单的 clearValidate() 函数清理上次的校验结果,如果没有这一步,表单校验的结果就会显得错乱。
https://github.com/yiminghe/async-validator