Element、iview 表单校验总结
本文分享主要内容:
基本用法、校验方式、部分校验(关联交验)、新增校验、 动态切换校验、校验/重置Form表单、日期选择器关联
1. 基本用法(Element、iview 这些用法都是大同小异)
注意:
- ref/rules/model/prop属性是必须的
- ref/rules/model和FormItem中的prop绑定的对象的字段要相对应
- Form是根据FormItem的prop属性来验证,所以prop一定要写在FormItem上
- prop属性的值一定要在Form表单.后面能够找的到,(如:formData.list[0].name)
<!-- 基本用法 -->
<Form :model="formData" :rules="rules" ref="ruleForm">
<Form-item label="险种名称" prop="name">
<Input v-model="formData.name"></Input>
</Form-item>
</Form>
<!-- 多层嵌套,prop一定要写在FormItem上-->
<Form-item class="plant-days-item" label="种植后多久可投">
<Form-item :prop="plantDaysStart">
<Input v-model="plantDaysStart" placeholder="请输入最小可投天数"></Input>
</Form-item>
<span class="cut">~</span>
<Form-item :prop="plantDaysEnd">
<Input v-model="plantDaysEnd" placeholder="请输入最大可投天数"></Input>
</Form-item>
</Form-item>
2. 校验方式
注意:
- 做表单必填校验的时候,一定要注意值的类型
- 有时表单验证select时,验证失败,要加上type: 'number'
- 日期选择器验证,要加上type: 'date'
- 级联选择或者多选框等,要加上type: 'array'
- select和日期选择器等,trigger: 'change'
默认(如 required,min, max等)
name: [
{ required: true, message: '必填', trigger: 'blur' },
{ min: 6, max: 18, message: '长度在6~18个字符', trigger: 'blur' }
],
type: { required: true, type: 'number', message: '请选择', trigger: 'change' },
time: [{required: true, type: 'date', message: '请选择日期', trigger: 'change'}],
list: { required: true, type: "array", message: "请至少选择一个", trigger: "change" }
正则(手机号,邮箱,密码等,过长或多处使用可以在外部定义一个常量)
const RESET_PASS_REG = /^(?=.*[0-9])(?=.*[a-zA-Z]).*[0-9A-Za-z\u4e00-\u9fa5!@#$%^&*]{6,30}$/;
password: { pattern: RESET_PASS_REG, message: '密码长度6-30位,至少含有数字&字母', trigger: 'blur'},
phone: [{
pattern: /^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0,5-9]))\d{8}$/,
message: '手机格式不正确',
trigger: 'blur'
}],
自定义(可以自定义各种需要的情形,如果使用到了data内部的数据,需要定义在data()内才行)
const validateIdentifyNumber = (rule, value, callback) => {
if (!value) {
return callback(new Error("请输入证件号码"));
}
if (getStrCharLen(value) > 40) {
return callback(new Error("证件号码长度最多40个字符"));
}
if (/[\u4E00-\u9FA5]/g.test(value)) {
return callback(new Error("证件号码不能含有中文"));
}
callback();
};
identifyNumber: { required: true, validator: validateIdentifyNumber, trigger: "blur" }
3.部分校验/关联校验(对部分表单字段进行校验 validateField )
注意:
- 比如校验的是树(Tree)结构数据或者另外组件数据等,数据发生变化时,手动触发校验
- 关联校验时,有时会出现失效(输入框右侧一直loading);需要执行callback()
- validateField的参数要与prop绑定的值相同
editorContent(html) {
this.insureForm.desc = html;
this.$refs.insureForm.validateField('desc'); //手动触发校验
}
const validatePassword = (rule, value, callback) => {
if (this.passwordFrom.checkPassword !== '') {
callback(this.$refs.passwordFrom.validateField('checkPassword'));
}
callback();
};
const validateCheckPassword = (rule, value, callback) => {
if (value !== this.passwordFrom.password) {
callback(new Error('两次密码不一致,请重新输入'));
}
callback();
};
password: { required: true, validator: validatePassword, trigger: 'blur' },
checkPassword: { required: true, validator: validateCheckPassword, trigger: 'blur' }
4. 新增表单校验
注意:
- v-for循环Form子属性ruleList
- 循环的FormItem的prop属性为[子属性].[索引值].[子属性]
- 循环的FormItem手动指定rules
- 循环中的关联校验,可以通过自定义校验规则拿到当前值的索引值来实现
<Form-item class="add-time-item" label="投保规则" prop="ruleList">
<div
v-for="(item, index) in insurableForm.ruleList"
:key="index"
class="insurable-rule-list"
>
<Form-item class="plant-days-item" label="种植后多久可投">
<Form-item
:rules="insurableRule.plantDaysStart"
:prop="`ruleList.${index}.plantDaysStart`"
>
<Input v-model="item.plantDaysStart" placeholder="请输入"></Input>
<span class="unit">天</span>
</Form-item>
<span class="cut">~</span>
<Form-item
:rules="insurableRule.plantDaysEnd"
:prop="`ruleList.${index}.plantDaysEnd`"
>
<Input v-model="item.plantDaysEnd" placeholder="请输入"></Input>
<span class="unit">天</span>
</Form-item>
</Form-item>
</div>
</Form-item>
const plantDaysStartRule = (rule, value, callback) => {
let index = rule.field.split('.')[1];
if (!/^[1-9][0-9]?$/.test(value)) {
callback(new Error('请输入1~99'));
}
if (this.insurableDetailForm.ruleList[index].plantDaysEnd &&
this.insurableDetailForm.ruleList[index].plantDaysEnd - value <= 0) {
callback(new Error('开始时间应小于结束时间'));
}
callback();
};
const plantDaysEndRule = (rule, value, callback) => {
let index = rule.field.split('.')[1];
if (!/^[1-9][0-9]?$/.test(value)) {
callback(new Error('请输入1~99'));
}
if (this.insurableDetailForm.ruleList[index].plantDaysStart) {
callback(this.$refs.insurableDetailForm.validateField(`ruleList.${index}.plantDaysStart`));
}
callback();
};
plantDaysStart: { required: true, validator: plantDaysStartRule, trigger: 'blur' },
plantDaysEnd: { required: true, validator: plantDaysEndRule, trigger: 'blur' }
5. 动态切换校验
注意:
- 表单初始化时必填项要设置校验,否则必填符号不显示,除非重新渲染Form表单
- 动态切换校验时,要先通过length判断一下校验是否已经存在,防止重复添加
// 添加账户时判断是否已有校验,若没有则添加校验
addRuleValidate() {
if(this.ruleValidate.password.length < 1){
this.ruleValidate.password.unshift({validator: (rule, value, callback) => {
if (!value) {
callback(new Error('登录密码不能为空'))
}
if (!/^(?=.*[0-9])(?=.*[a-zA-Z]).*[0-9A-Za-z\u4e00-\u9fa5!@#$%^&*]{6,30}$/.test(value)) {
callback(new Error('登录密码由6-30位含有数字和字母组成'))
}
callback()
}, required: true, trigger: 'blur'});
this.ruleValidate.role.unshift({required: true, message: '角色不能为空', type: 'number', trigger: 'change'});
this.ruleValidate.realName.unshift({required: true, message: '姓名不能为空', trigger: 'blur'});
this.ruleValidate.company.unshift({required: true, message: '工作单位不能为空', trigger: 'blur'});
}
},
// 修改密码时删除一些不要的校验
pwdRuleValidate() {
this.ruleValidate.role.shift();
this.ruleValidate.realName.shift();
this.ruleValidate.company.shift();
}
6. 校验/重置Form表单
注意:
- 通过$ref访问到Form组件,调用validate函数,获取相应的校验结果
- 通过$ref访问到Form组件,调用resetFields函数,移除重置表单及校验结果
- FormItem的prop属性要与表单组件v-model绑定的对象的字段相对应
- 使用v-if切换表单状态,会导致已经绑定的校验规则失效
a. 可选用v-show替代v-if
b. 直接将校验规则写在FormItem上
// 提交表单
submitForm(name){
this.$refs[name].validate((valid) => {
if (valid) {
this.$Message.success('校验通过!');
}else {
this.$Message.error('校验失败!');
}
}
},
// 重置表单
resetForm(name){
this.$refs[name].resetFields();
}
<!-- 直接将校验规则写在FormItem上 -->
<Form-item
label="险种名称"
prop="name"
:rules="[{ required: true, message: '请输入险种名称', trigger: 'blur' }]"
>
<Input v-model="insureForm.name"></Input>
</Form-item>
7. 日期选择关联
注意:
- 为每一个DatePicker配置options属性
- 监听ruleList的length属性变化,重置每一个DatePicker的options
<Form-item class="add-time-item" label="投保规则" prop="ruleList">
<div
v-for="(item, index) in insurableForm.ruleList"
:key="index"
class="insurable-rule-list"
>
<Form-item
:rules="insurablelRule.plantStartTime"
label="种植起始时间"
:prop="`ruleList.${index}.plantStartTime`"
>
<DatePicker
type="date"
clearable
v-model="item.plantStartTime"
format="MM-dd"
placeholder="请选择种植起始时间"
:options="datePickerOptions[index].plantStartTimeOptions"
></DatePicker>
</Form-item>
<Form-item
:rules="insurablelRule.plantEndTime"
label="种植截止时间"
:prop="`ruleList.${index}.plantEndTime`"
>
<DatePicker
type="date"
clearable
v-model="item.plantEndTime"
format="MM-dd"
placeholder="请选择种植截止时间"
:options="datePickerOptions[index].plantEndTimeOptions"
></DatePicker>
</Form-item>
</div>
</Form-item>
watch: {
'insurableForm.ruleList.length': {
immediate: true,
handler() {
let len = this.insurableForm.ruleList.length;
if (len) {
this.datePickerOptions = [];
for (let i = 0; i < len; i++) {
this.datePickerOptions.push({
plantStartTimeOptions: {
disabledDate: date => {
if (this.insurableForm.ruleList[i].plantEndTime) {
let year = new Date();
year.setYear(new Date(this.insurableForm.ruleList[i].plantEndTime).getFullYear() - 1);
year.setMonth(11, 31);
return date >= this.insurableForm.ruleList[i].plantEndTime || date <= year;
}
}
},
plantEndTimeOptions: {
disabledDate: date => {
if (this.insurableForm.ruleList[i].plantStartTime) {
let year = new Date();
year.setYear(new Date(this.insurableForm.ruleList[i].plantStartTime).getFullYear());
year.setMonth(11, 31);
return date <= this.insurableForm.ruleList[i].plantStartTime || date >= year;
}
}
}
});
}
}
}
}
}
发表评论 (审核通过后显示评论):