三分钟细数 el-form 表单校验的坑点,前车之鉴,可助你避坑

背景

Vue 的 el-form 提供了表单校验功能, :rules 属性设置校验规则,并通过 el-form-item 的 prop 属性绑定校验规则。组件封装,让前端校验更方便。

具体使用过程中,有几个容易出错的地方,本文来整理一下。每一个坑都是笔者亲自趟过的,写完本文后,以后应该不会再踏入相同的坑。

el-form 的 model 属性

el-form 的 model 属性是用来指定表单使用的数据的,虽然 el-form 指定了 model 对象,但是,理论上,vue 并没有限制 el-input 绑定的数据,el-form 内部的 el-input 组件依然可以绑定其他数据。

需要注意的是,如果要用 rules 进行表单校验,那么 el-input 绑定的元素必须是 el-form 的 model 的直接属性,否则会导致校验失败。

<el-form :model="groupData" :rules="rules" ref="groupForm">
	<el-form-item label="分组名称:" prop="name">
	  <el-input v-model="groupData.name"/>
	</el-form-item>
</el-form>

这段代码中 el-form 的 model 是 groupData,那么 el-form-item 中所有需要校验的表单的 model 也必须是 groupData.xxx ,即 groupData 对象的直接属性。

el-from-item 的 prop 属性

el-from-item 的 prop 属性必须与 el-input 中需要校验的表单属性一致。

<el-form-item label="x" prop="name">
            <el-input v-model="data.name" />
</el-form-item>

要校验的表单 model 是 data.name,那么 prop 的值也必须是 name,否则无法正确完成校验,出现明明已经输入了表单值,但是还是出现校验失败的提示信息。

另外,如果 prop 属性根据当前表单值动态设置,例如,当前表单值为空时,不需要校验:

:prop="form.myProp !== null && form.myProp != '' ? 'myProp' : ''"

这种情况下,当 form.myProp 非空时,虽然显示有校验属性,但是使用 formRef.validate 触发整个表单的校验时,这个 myProp 属性的 表单不会触发校验。

动态设置 prop 校验属性的需求遇到过不少,但是都是根据关联的其他属性控制的,没有遇到多根据自身表单值控制 prop 的情况。尝试手动调用 validateField('myProp') 的时候报 Vue props 错误的。

推断:这种根据自己值设置 prop 后,实际上这个表单并没有刷新到最新的校验 prop 值,所以表单校验时不认为它包含校验规则。

多表单校验

el-form-item 内部如果包含多个表单,默认校验失败时会将所有表单高亮,例如:
在这里插入图片描述
虽然只有第二个表单没有输入,但是校验失败时会同时高亮两个表单。怎么只对第二个表单高亮呢?

解决办法是用嵌套:
外层 el-form-item 是正常的信息,内层对第二个表单再次嵌套 el-form-item 指定校验属性:

<el-form-item label="任务执行时间:" required>
    <el-select v-model="data.executeCycle">
      <el-option label="时" value="hour">时</el-option>
      <el-option label="日" value="day">日</el-option>
      <el-option label="周" value="week">周</el-option>
    </el-select>
    <el-form-item prop="tme">
      <el-date-picker v-model="data.executeTime"
		      type="datetime"
		      value-format="yyyy-MM-dd HH:mm:ss"
		      placeholder="选择日期时间"
		      default-time="00:00:00">
      </el-date-picker>
    </el-form-item>
</el-form-item>

将日期输入框包裹在新的 el-form-item 中,外层的 el-form-item 添加 requred 显示前面的红星,就可以只对该属性校验了,将第二个表单再嵌套后,校验结果就正常了:

在这里插入图片描述
嵌套表单如果是放在 el-form 中,直接嵌套后会出现样式错乱问题:
在这里插入图片描述
解决办法是为嵌套在内部的 el-form-item 添加额外样式:

<el-form-item label="XXX:">
  <el-radio-group v-model="a.name" >
    <el-radio-button label="0"></el-radio-button>
    <el-radio-button label="1"></el-radio-button>
  </el-radio-group>
  <el-form-item style="margin-top: -23px;margin-left: 50px;" v-if="a.continuity === '1'" prop="continuityNum">
    <el-input v-model="a.b" ></el-input>
  </el-form-item>
</el-form-item>

这样就齐了:
在这里插入图片描述

复杂属性

<el-form-item label="执行周期 " prop="config.gapTime">
            <el-input    type="number" :min="1" v-model="data.config.gapTime">
            </el-input>
  <el-form-item>

此时,该属性对应的 rules 定义也必须是对象

rules: {
        config: {
          gapTime: [
            { required: true, message: '请输入执行周期', trigger: 'blur' },
          ],
        },
      },

否则,就会出现明明已经输入了值,但是还是提示校验错误信息。

v-if 控制的表单不触发校验

如果一个表单需要校验,那么它不应该使用 v-if 控制,否则初始时组件没有创建,校验规则就不会绑定,也不会生效。例如下面的例子,根据任务类型,配置执行时间:

<el-form-item label="执行时间:"
              v-if="type === '单次任务'"
              prop="executeTime">
  <el-date-picker 
                  v-model="form.executeTime"
                  type="datetime"
                  value-format="yyyy-MM-dd HH:mm:ss"
                  placeholder="选择执行时间">
  </el-date-picker>
</el-form-item>
<el-form-item label="执行Cron表达式:"
              v-if="type === 'Cron任务'"
              prop="executeCron">
  <el-input  v-model="form.executeCron" placeholder="调度周期">
  </el-input>
</el-form-item>

初始化时第一个时间表单如果没有,那么当它重新生成时,上面的校验无效。

这个问题的根源是两个 el-form 元素没有作区分标识,v-if 动态切换时,Vue 内部误以为是同一个元素,导致跳转时触发校验。

解决办法:使用 v-show/v-if 控制显示和隐藏,同时为它们的给 el-form-item 元素添加不同的 key 属性值。

动态显示隐藏的表单切换后

动态显示隐藏的表单切换后,应该清空上次的表单校验结果:
this.$refs.myForm.clearValidate('xx');

否则相同位置的校验结果会混乱的。

表格数据校验

参考:https://blog.csdn.net/qq_43523725/article/details/123214343

核心:
1、必须使用嵌套属性,即表格列表的数组应该是某个属性的值。例如:

{
  elTableModel: {
       tableData: [] 
  }
}

2、外层的 el-form 的 :model 属性是必须的,否则输入不会和校验属性绑定。
demo:

<el-form :model="elTableModel" ref="propForm"  :rules="rules">
          <el-table :data="elTableModel.tableData">
            <el-table-column  prop="fieldName" label="AAA">
              <template slot-scope="scope">
                <el-form-item label-width="0px"
                              :prop="'tableData.'+scope.$index + '.name'"
                              :rules='logicTableRules.name'>
                  <el-input v-model="scope.row.name"  clearable>
     </el-input>
     </el-form-item>
   </template>
 </el-table-column>
 </el-table>
 </el-form>

自定义校验规则

注意事项: 自定义校验规则的时候,必须保证各个分支且至少有一个分支执行 callback() 函数,否则会导致表单校验操作 validate 阻塞而无返回结果。

例如,自定义一个正则限定 APIUrl 输入:

apiUrl: [
            { validator: (rule, value, callback) => {
                const pattern = /^https?:\/\/([a-zA-Z0-9_]|[_\/\.:#\-]){2,50}$/;
                if (value === null || value === '') {
                  callback(new Error(`请输入接口URL`));
                } else if (!pattern.test(value)) {
                  callback(
                    new Error(
                      'http:// 或 https:// 开头',
                    ),
                  );
                } else {
                  callback();
                }
              },
              required: true, trigger: ['blur']
            },
          ],

这个 validator 分支完整,且校验通过后能执行 callback() 函数,外层对表单的 validate() 异步校验就能正常结束。

启示录

表单校验的时候,犯了几个低级错误,记录如下:

  1. el-form 下的 el-input 使用的数据不是 el-form 的 model 数据,导致校验失败;
  2. el-form 表单初始化指定的 model 数据的属性值,少于 el-form-item 引用的属性值,导致触发校验失败。比如 model 属性有三个变量,但是实际表单有四个,且都有校验规则,那么即使输入了值,表单校验也通不过。
  3. el-form 的 :rules 属性敲错了,忘记了冒号,导致传递的是个字符串;
  4. el-form-item 的 prop 和 el-input 表单的属性不一致导致校验失败。
  5. 自定义 validator 的分支中漏掉了正常输入时 callback() 调用,导致 validate 在输入正确时阻塞无返回值。

表单校验还有三种常见问题:

  • please transfer a valid prop path to form item 属性绑定问题
  • 表单位于 el-popover 中
  • 动态生产的表单校验

下一节将继续介绍这两个问题的解决办法。

  • 18
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
el-form 提供了很多内置的表单校验规则,但是有时候我们需要自定义校验规则来满足业务需求。在 el-form 中自定义校验可以通过 rules 属性来实现。具体步骤如下: 1. 在 el-form 中设置 rules 属性,并定义一个对象来存储自定义校验规则,例如: ``` <el-form :model="form" :rules="rules"> ... </el-form> data() { return { form: { ... }, rules: { name: [ { required: true, message: '请输入姓名', trigger: 'blur' }, { validator: this.checkName, trigger: 'blur' } ] } } }, ``` 2. 在 rules 对象中定义校验规则,可以使用内置的校验规则,也可以自定义 validator 规则。例如: ``` checkName(rule, value, callback) { const reg = /^[\u4e00-\u9fa5]{2,4}$/; // 中文姓名的正则表达式 if (value && !reg.test(value)) { callback(new Error('请输入正确的中文姓名')); } else { callback(); } } ``` 在自定义 validator 规则中,第一个参数 rule 是当前校验规则的配置对象,第二个参数 value 是当前表单项的值,第三个参数 callback 是回调函数,用于返回校验结果。如果校验不通过,需要调用 callback(new Error('错误提示')) 方法,如果校验通过,则直接调用 callback() 方法即可。 3. 在 el-form-item 中设置 prop 属性来指定当前表单项的 model 字段,并设置 :rules 属性来指定当前表单项的校验规则。例如: ``` <el-form-item label="姓名" prop="name"> <el-input v-model="form.name"></el-input> </el-form-item> ``` 通过以上步骤即可实现 el-form 中的自定义校验
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值