ByteNoteByteNote

字节笔记本

2026年2月19日

ElementUI 循环生成 Form 表单的动态校验方案

API中转
¥120

本文介绍在 ElementUI 中使用循环生成的 Form 表单如何添加动态校验规则,解决动态表单验证的常见问题。

核心问题

在 ElementUI 中使用 v-for 循环生成的表单,需要为每个动态生成的表单项添加校验规则。这是一个常见的开发场景,但由于动态 prop 绑定的语法较为特殊,很多开发者会遇到校验不生效的问题。

动态 prop 绑定语法

循环生成表单时,prop 属性的绑定需要使用特殊语法:

:prop="`getAllTableData.${i}.value`"

其中:

  • getAllTableData 是 v-for 绑定的数组
  • i 是当前项的索引
  • value 是表单绑定的 v-model 名称

完整代码示例

HTML 模板部分

html
<el-form ref="dialogRef" :model="getAllFormData">
  <template v-for="(item, i) in getAllFormData.getAllTableData">
    <!-- 下拉框 -->
    <el-form-item
      v-if="item.selectFlag"
      :prop="`getAllTableData.${i}.value`"
      :rules="item.rule"
      :label="item.labelName"
    >
      <el-select v-model="item.value">
        <el-option
          v-for="item1 in item.selectOption"
          :key="item1.value"
          :label="item1.label"
          :value="item1.value"
        >
        </el-option>
      </el-select>
    </el-form-item>

    <!-- 禁用输入框 -->
    <el-form-item
      v-else-if="!item.hidden && item.disabled"
      :prop="`getAllTableData.${i}.value`"
      :rules="item.rule"
      :label="item.labelName"
    >
      <el-input v-model="item.value" :disabled="true"></el-input>
    </el-form-item>

    <!-- 普通输入框 -->
    <el-form-item
      v-else-if="!item.hidden"
      :prop="`getAllTableData.${i}.value`"
      :rules="item.rule"
      :label="item.labelName"
    >
      <el-input v-model="item.value"></el-input>
    </el-form-item>
  </template>
</el-form>

Vue Data 结构

javascript
data() {
  return {
    getAllFormData: {
      getAllTableData: [
        {
          labelName: "规则ID",
          value: "",
          propName: "ruleid",
          disabled: true,
          hidden: true,
          rule: { required: false }
        },
        {
          labelName: "编码",
          value: "",
          propName: "code",
          rule: {
            validator: (rule, value, callback) => {
              if (value == "") {
                callback();
              } else {
                let reg = /[\u4E00-\u9FA5\uF900-\uFA2D]/;
                if (reg.test(value)) {
                  callback(new Error("请输入英文或数字"));
                } else {
                  callback();
                }
              }
            },
            trigger: "blur"
          }
        },
        {
          labelName: "评分",
          value: "",
          propName: "mark",
          rule: {
            required: true,
            validator: (rule, value, callback) => {
              if (value == "") {
                callback(new Error("请输入数字"));
              } else {
                let reg = /^[0-9]+(.[0-9]{1})?$/;
                if (!reg.test(value) || value > 100) {
                  callback(new Error("请输入0-100的有效数字,可保留一位小数"));
                } else {
                  callback();
                }
              }
            },
            trigger: "blur"
          }
        },
        {
          labelName: "警告标识",
          value: "",
          propName: "warnsign",
          selectFlag: true,
          selectOption: [
            { value: "0", label: "否" },
            { value: "1", label: "是" }
          ],
          rule: {
            required: true,
            message: "请选择对应的选项"
          }
        }
      ]
    }
  }
}

动态增减表单项

除了固定数量的循环表单,还可以实现动态增减表单项:

html
<el-form :model="upsertForm" ref="upsertForm">
  <el-form-item
    v-for="(domain, index) in upsertForm.domains"
    :label="'专利号' + index"
    :key="domain.key"
    :prop="'domains.' + index + '.value'"
    :rules="{ required: true, message: '专利号不能为空', trigger: 'blur' }"
  >
    <el-input v-model="domain.value"></el-input>
    <el-button @click.prevent="removeDomain(domain)">删除</el-button>
  </el-form-item>

  <el-form-item>
    <el-button type="primary" @click="addDomain">新增专利号</el-button>
  </el-form-item>
</el-form>
javascript
data() {
  return {
    upsertForm: {
      domains: [
        { key: 1, value: '' }
      ]
    }
  }
},
methods: {
  addDomain() {
    this.upsertForm.domains.push({
      key: Date.now(),
      value: ''
    });
  },
  removeDomain(domain) {
    const index = this.upsertForm.domains.indexOf(domain);
    if (index !== -1) {
      this.upsertForm.domains.splice(index, 1);
    }
  }
}

关键注意点

重要:循环的文本框隶属于 form 表单,form 表单绑定的是 upsertForm,所以它的对象必须要在 upsertForm 里面,校验才能生效。

校验规则配置方式

配置方式适用场景示例
简单规则必填、长度等基础校验{ required: true, message: '请输入', trigger: 'blur' }
自定义校验复杂业务逻辑校验使用 validator 函数
正则校验格式验证结合 validator 使用正则表达式

自定义校验函数模板

javascript
{
  validator: (rule, value, callback) => {
    if (value === '') {
      callback(new Error('请输入内容'));
    } else if (!/^[a-zA-Z0-9]+$/.test(value)) {
      callback(new Error('只能输入英文和数字'));
    } else {
      callback(); // 校验通过
    }
  },
  trigger: 'blur'
}

表单验证方法

javascript
methods: {
  // 提交表单时验证
  submitForm() {
    this.$refs.dialogRef.validate((valid) => {
      if (valid) {
        console.log('表单验证通过', this.getAllFormData);
        // 执行提交操作
      } else {
        console.log('表单验证失败');
        return false;
      }
    });
  },

  // 重置表单
  resetForm() {
    this.$refs.dialogRef.resetFields();
  }
}

常见问题

1. 校验不生效

原因:prop 绑定路径错误,或数据不在 form 的 model 中。 解决:确保 :prop="'domains.' + index + '.value'" 路径正确,且数据在 upsertForm.domains 中。

2. 重置表单无效

原因:表单项没有设置 prop。 解决:每个 el-form-item 都必须设置 prop 属性。

3. 动态添加项后校验异常

原因:新添加的项没有正确初始化。 解决:确保新增项包含完整的字段结构。

总结

ElementUI 循环生成表单的校验核心要点:

  1. prop 绑定语法:使用模板字符串 :prop="domains.${index}.value"
  2. 数据结构:校验的字段必须在 form 的 model 对象内
  3. rules 配置:支持简单规则和自定义校验函数
  4. 动态增减:配合数组方法实现动态表单项

掌握这些技巧后,可以灵活应对各种动态表单校验场景。

分享: