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

循环多组日期选择框,为每组设置自己可选择范围,且互不影响
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269