在 ElementUI 中,循环生成表单并进行校验的核心在于 动态绑定 prop 属性,让每个表单项都能与数据数组中的对应字段正确关联。
基本原理:动态绑定 Prop
当使用 v-for 循环生成表单项时,不能使用静态的 prop。你需要使用动态绑定的方式,指定当前表单项对应的是数据数组中的哪个具体字段。
动态 prop 的通用语法格式为:
javascript
:prop="'数组名.' + 索引 + '.字段名'"
两种常见场景与实现方法
根据你的具体需求,主要可以分为以下两种情况,其实现对比见下表:
| 场景特点 | 数据结构示例 | 关键设置 (prop) |
如何触发校验 |
|---|---|---|---|
| 场景一:v-for循环单个表单 (如动态增减的输入项) | form: { domains: [ {value: ''}, {value: ''} ] } |
:prop="'domains.' + index + '.value'"-2 |
调用 this.$refs.formRef.validate() |
场景二:校验多个独立表单 (如多个<el-form>组件) |
多个独立的表单数据对象 | 每个表单设置独立的 ref (如 formA, formB)-5 |
使用 Promise.all() 逐一校验每个表单的 ref-5 |
场景一:循环渲染单个表单内的项目
这是最常见的动态表单,比如可以自由添加或删除的输入项列表-1。你需要确保 prop 通过索引与数组数据精确绑定。
html
<el-form :model="form" :rules="rules" ref="dynamicFormRef">
<el-form-item
v-for="(domain, index) in form.domains"
:key="index"
:label="'域名' + index"
:prop="'domains.' + index + '.value'"
:rules="{ required: true, message: '域名不能为空', trigger: 'blur' }"
>
<el-input v-model="domain.value"></el-input>
</el-form-item>
<el-button @click="submitForm('dynamicFormRef')">提交</el-button>
</el-form>
场景二:一键校验多个独立的表单
如果你的页面有多个完全独立的 <el-form>,需要一次性全部校验通过后才能提交,可以结合 Promise 来实现。
-
为每个表单设置独立的
ref:html<el-form ref="formA">...</el-form> <el-form ref="formB">...</el-form> <el-form ref="formC">...</el-form> -
提交时使用
Promise.all进行批量校验:javascriptmethods: { submitAllForms() { let promises = ['formA', 'formB', 'formC'].map(refName => { return new Promise((resolve, reject) => { this.$refs[refName].validate((valid) => { valid ? resolve() : reject(); }); }); }); Promise.all(promises) .then(() => { // 所有表单验证通过 this.$message.success('所有表单校验通过!'); // 执行后续提交逻辑... }) .catch(() => { this.$message.error('请检查表单填写是否正确'); }); } }
注意事项与最佳实践
-
ref在循环中的使用 :如果在v-for内部使用ref,得到的会是一个包含所有DOM节点或组件实例的数组,管理起来比较复杂。通常建议将ref放在外层的<el-form>上-1。 -
处理异步校验 :如果校验规则中包含需要调用接口的异步校验,确保校验函数正确返回
Promise。在批量校验多个表单时,Promise.all本身就能很好地处理异步任务-1。 -
表单嵌套表格 :如果你的表单内嵌了
el-table,并对每一行数据都需要校验,方法与场景一类似。关键点同样是在表格单元格内的<el-form-item>上,使用:prop="'tableData.' + scope.$index + '.fieldName'"的格式来动态绑定规则