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;
                }
              }
            }
          });
        }
      }
    }
  }
}
循环多组日期选择框,为每组设置自己可选择范围,且互不影响

循环多组日期选择框,为每组设置自己可选择范围,且互不影响

本文章由javascript技术分享原创和收集

发表评论 (审核通过后显示评论):