常见的表单验证是对 对象中 单个字段的验证,那如何对数组中的每一项做到验证呢?例如,我们有这样一个需求:公司系统需要录入员工信息,可以同时添加多个员工并且对这些信息进行格式校验,实现如下效果:
首先需要准备好 form 数据和 rules 验证规则
form: {
member: [
{ name: "", sex: "", age: "" }
],
},
rules: {
name: { required: true, message: "请输入姓名" },
sex: { required: true, message: "请选择性别" },
age: { required: true, message: "请选择年龄" },
},
然后在 form 中去循环 member 数组,将三个 formItem 当成一组,循环生成多组数据,这样就实现了数组表单。接下来就是实现表单验证:
表单验证必须要给 form-item 设置 name 属性,name 接受两种形式
name = "age"
,校验 form 中的 age 字段:name="['member', index, 'age']"
,校验 form 中的 member 数组,对数组中的第 index 项的 age 字段进行格式验证,可以理解为校验 member[index].age
字段<a-form ref="formRef" :model="form">
<div class="member" v-for="(item, index) in form.member" :key="item">
<a-form-item
label="姓名"
:name="['member', index, 'name']"
:rules="rules.name"
>
<a-input v-model:value="item.name" />
</a-form-item>
<a-form-item
label="性别"
:name="['member', index, 'sex']"
:rules="rules.sex"
>
<a-select v-model:value="item.sex">
<a-select-option value="1"> 男 </a-select-option>
<a-select-option value="0"> 女 </a-select-option>
</a-select>
</a-form-item>
<a-form-item
label="年龄"
:name="['member', index, 'age']"
:rules="rules.age"
>
<a-input v-model:value="item.age" />
</a-form-item>
</div>
</a-form>
最后就是一些细节的实现:增加 item 项、删除 item 项、提交表单、重置表单。
以下附上 form-valid.vue 的全部代码
<template>
<h2 style="margin-bottom: 20px">Form 数组表单验证</h2>
<a-form ref="formRef" :model="form">
<div class="member" v-for="(item, index) in form.member" :key="item">
<a-form-item
label="姓名"
:name="['member', index, 'name']"
:rules="rules.name"
>
<a-input v-model:value="item.name" />
</a-form-item>
<a-form-item
label="性别"
:name="['member', index, 'sex']"
:rules="rules.sex"
>
<a-select v-model:value="item.sex">
<a-select-option value="1"> 男 </a-select-option>
<a-select-option value="0"> 女 </a-select-option>
</a-select>
</a-form-item>
<a-form-item
label="年龄"
:name="['member', index, 'age']"
:rules="rules.age"
>
<a-input v-model:value="item.age" />
</a-form-item>
<a-form-item>
<a-button @click="delItem(index)">
<MinusOutlined />
</a-button>
</a-form-item>
</div>
</a-form>
<a-button class="add-btn" @click="addItem"><PlusOutlined /></a-button>
<a-button type="primary" html-type="submit" @click="submitForm">Submit</a-button>
<a-button @click="resetForm">Reset</a-button>
</template>
<script>
import { Form, Input, Select, Button } from "ant-design-vue";
import { MinusOutlined, PlusOutlined } from "@ant-design/icons-vue";
export default {
components: {
[Form.name]: Form,
[Form.Item.name]: Form.Item,
[Input.name]: Input,
[Select.name]: Select,
[Select.Option.displayName]: Select.Option,
[Button.name]: Button,
MinusOutlined,
PlusOutlined,
},
data() {
return {
form: {
member: [
{ name: "", sex: "", age: "" }
],
},
rules: {
name: { required: true, message: "请输入姓名" },
sex: { required: true, message: "请选择性别" },
age: { required: true, message: "请选择年龄" },
},
};
},
methods: {
submitForm() {
this.$refs.formRef.validate().then(() => {
console.log(123);
}, (err) => {
console.log(err);
});
},
resetForm() {
this.$refs.formRef.resetFields();
},
addItem() {
const item = { name: "", sex: "", age: "" };
this.form.member.push(item);
},
delItem(i) {
if (this.form.member.length === 1) {
return;
}
this.form.member.splice(i, 1);
},
},
};
</script>
<style lang='less' scoped>
.member {
display: flex;
.ant-form-item {
margin-right: 10px;
width: 200px;
}
}
.ant-btn {
margin-right: 10px;
}
</style>```