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)



  
    
  
  ~
  
    
  

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
  • 循环中的关联校验,可以通过自定义校验规则拿到当前值的索引值来实现

  
~
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();
}


  

7. 日期选择关联

注意:

  • 为每一个DatePicker配置options属性
  • 监听ruleList的length属性变化,重置每一个DatePicker的options

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

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

你可能感兴趣的:(Element、iview 表单校验总结)