vue+element动态新增表单并校验

本文介绍如何在Vue中使用Element UI实现表单的动态添加与数据验证,特别是针对汽车类型选择的下拉列表,确保每次添加的新项都能正确进行表单验证。

在这里插入图片描述
在这里插入图片描述

   <el-button @click="addCarType">添加</el-button>

            <el-form :model="detailList"  label-width="120px" class="demo-ruleForm"  ref="detailList" :rules="formRules">
                <div v-for="(item,index) in detailList.carType" :key="item.type">
                    <el-form-item :label="$t('car.add.carType')" :prop="'carType.' + index +'.type'" :rules="formRules.change">
                    <el-select v-model="item.type">
                        <el-option v-for="item in carTypeOptions" :key="item.key" :value="item.value" :label="$t(item.label)"></el-option>
                    </el-select>
                    </el-form-item>
                </div>
            </el-form>
            
   <el-button @click="submitForm">提交</el-button>

<script lang="ts">
import Vue from 'components/base'
import { Component } from 'vue-property-decorator'
import { formRules } from "../common/validator";
import {  CarType  } from 'common/enums'
@Component({
    components: {}
})
export default class CarInfo extends Vue {
    public formRules = formRules;

    public $refs:{
        detailList: HTMLFormElement
    }
    public detailList:any ={
        address:'XXX',
        carType:[
        	{type:'',length:''}
        ]
    }
    public carTypeOptions = CarType.getSelect(false)

    public addCarType (){
        this.detailList.carType.push({type:'',length:''})
    }

    public submitForm (){
        this.$refs.detailList.validate(vaild=>{
            if(vaild){

            }else{
                this.$message.error("验证不通过");
            }
        })
    }
}

注意正常验证表单项是prop,而这里是:prop。
:prop="‘carType.’ + index +’.type’"是拼接的形式,前面是v-for绑定的数组,中间是数组索引index,最后是表单项绑定的v-model的名称,然后用点.把它们连接起来。这三项都必须保证正确,错一个都无法验证。

//表单校验规则
export var formRules = {
    blur: [
        { required: true, pattern: /\S/, message: '此项为必填项', trigger: 'blur' },
    ],
    /* select框 */
    change: [
        { required: true, message: '此项为必填项', trigger: 'change' },
    ],
    default:[]
}
<think>我们正在使用Vue2和Element UI实现动态增减表单添加表单校验功能。 步骤: 1. 使用`el-form`组件,设置`model`和`rules`。 2. 在`el-form`内部,使用`v-for`循环生成多个表单项,每个表单项对应动态表单的一个字段。 3. 为每个表单项绑定`prop`,注意动态表单的`prop`应该是一个字符串,使用类似`'domains.' + index + '.value'`的形式。 4. 提供添加和删除表单项的方法。 5. 在添加表单项时,最好给每个表单项一个唯一的key(例如使用index),这样在删除时不会出错。 6. 定义校验规则,注意动态数组的每个元素的校验规则。 注意:Element UI的表单校验对于动态生成的表单项,需要确保每个表单项的prop是唯一的,且与rules中定义的规则路径一致。 示例代码结构: 模板部分: <el-form :model="dynamicForm" :rules="rules" ref="dynamicForm"> <div v-for="(domain, index) in dynamicForm.domains" :key="domain.key"> <el-form-item :prop="'domains.' + index + '.value'" :rules="rules.domains" > <el-input v-model="domain.value"></el-input> </el-form-item> <el-button @click.prevent="removeDomain(domain)">删除</el-button> </div> <el-button @click="addDomain">新增</el-button> </el-form> 数据部分: data() { return { dynamicForm: { domains: [] // 初始为空数组,每个元素是一个对象,如{ value: '' } }, rules: { domains: [ { required: true, message: '请输入内容', trigger: 'blur' } ] } }; }, methods: { addDomain() { this.dynamicForm.domains.push({ value: '', key: Date.now() // 使用时间戳作为key,确保唯一性 }); }, removeDomain(domain) { const index = this.dynamicForm.domains.indexOf(domain); if (index !== -1) { this.dynamicForm.domains.splice(index, 1); } } } 注意:这里我们为每个表单项对象添加了一个key属性,用于v-for的key,这样在删除时不会因为索引变化而导致渲染问题。 但是,上面的校验规则rules.domains是一个数组,直接用在每个表单项上。这样每个表单项都会应用同样的校验规则。 如果需要更复杂的校验,比如每个表单项可能有不同的规则,那么可以在rules中定义更复杂的结构,或者使用动态规则。 另外,在提交表单时,我们可以通过调用this.$refs.dynamicForm.validate()来校验整个表单。 完整示例: 模板: <template> <el-form :model="dynamicForm" :rules="rules" ref="dynamicForm" label-width="100px"> <el-form-item label="用户名"> <el-input v-model="dynamicForm.name"></el-input> </el-form-item> <div v-for="(domain, index) in dynamicForm.domains" :key="domain.key"> <el-form-item label="邮箱" :prop="'domains.' + index + '.value'" :rules="rules.email" > <el-input v-model="domain.value"></el-input> <el-button @click.prevent="removeDomain(domain)">删除</el-button> </el-form-item> </div> <el-form-item> <el-button type="primary" @click="submitForm('dynamicForm')">提交</el-button> <el-button @click="addDomain">新增邮箱</el-button> </el-form-item> </el-form> </template> 数据和方法: <script> export default { data() { return { dynamicForm: { name: '', domains: [] }, rules: { name: [ { required: true, message: '请输入用户名', trigger: 'blur' } ], email: [ { required: true, message: '请输入邮箱地址', trigger: 'blur' }, { type: 'email', message: '请输入正确的邮箱地址', trigger: ['blur', 'change'] } ] } }; }, methods: { submitForm(formName) { this.$refs[formName].validate((valid) => { if (valid) { alert('submit!'); } else { console.log('error submit!!'); return false; } }); }, addDomain() { this.dynamicForm.domains.push({ value: '', key: Date.now() }); }, removeDomain(domain) { const index = this.dynamicForm.domains.indexOf(domain); if (index !== -1) { this.dynamicForm.domains.splice(index, 1); } } } } </script> 注意:在动态表单中,我们为每个动态表单项的prop指定了路径,如'domains.0.value',这样校验器就能找到对应的值。 另外,在rules中,我们直接使用了email规则数组,这样每个邮箱输入框都会应用同样的规则。 这样,我们就实现了动态增减表单添加校验的功能。 相关问题: 1. 如果动态表单中每个表单项的校验规则不同,该如何处理? 2. 在动态表单中,如何实现整个表单校验? 3. 动态表单提交时,如何获取所有表单数据?</think>### Vue2 + Element UI 动态表单增减与校验实现 下面是在 Vue2 中使用 Element UI 实现动态增减表单添加校验的完整方案: #### 1. 基础模板结构 ```vue <template> <el-form :model="dynamicForm" :rules="formRules" ref="dynamicFormRef" label-width="100px" > <!-- 固定字段 --> <el-form-item label="用户名" prop="username"> <el-input v-model="dynamicForm.username" /> </el-form-item> <!-- 动态增减部分 --> <div v-for="(item, index) in dynamicForm.emails" :key="item.key" class="dynamic-item" > <el-form-item :label="`邮箱${index + 1}`" :prop="`emails.${index}.value`" :rules="emailRules" > <el-input v-model="item.value" /> <el-button type="danger" icon="el-icon-delete" @click="removeEmail(index)" circle ></el-button> </el-form-item> </div> <el-form-item> <el-button type="primary" @click="submitForm">提交</el-button> <el-button @click="addEmail">添加邮箱</el-button> </el-form-item> </el-form> </template> ``` #### 2. 数据与校验规则 ```javascript <script> export default { data() { // 邮箱字段校验规则 const validateEmail = (rule, value, callback) => { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (!value) { callback(new Error('邮箱不能为空')); } else if (!emailRegex.test(value)) { callback(new Error('请输入有效的邮箱地址')); } else { callback(); } }; return { dynamicForm: { username: '', emails: [{ value: '', key: Date.now() }] // 初始包含一个空项 }, formRules: { username: [ { required: true, message: '用户名不能为空', trigger: 'blur' } ] }, emailRules: [ { validator: validateEmail, trigger: 'blur' } ] }; }, methods: { // 添加邮箱字段 addEmail() { this.dynamicForm.emails.push({ value: '', key: Date.now() // 使用时间戳确保唯一key }); }, // 移除邮箱字段 removeEmail(index) { if (this.dynamicForm.emails.length > 1) { this.dynamicForm.emails.splice(index, 1); } else { this.$message.warning('至少需要保留一个邮箱'); } }, // 表单提交 submitForm() { this.$refs.dynamicFormRef.validate(valid => { if (valid) { // 处理提交逻辑 console.log('表单数据:', JSON.parse(JSON.stringify(this.dynamicForm))); this.$message.success('提交成功!'); } else { this.$message.error('请检查表单'); return false; } }); } } }; </script> ``` #### 3. 关键实现细节 1. **动态字段管理**: - 使用数组 `emails` 存储动态字段 - 每个字段包含唯一 `key` 确保 Vue 正确追踪 - 通过 `addEmail()` 和 `removeEmail()` 增减字段 2. **校验规则绑定**: - 使用 `:prop="emails.${index}.value"` 语法绑定动态路径 - 自定义 `validateEmail` 函数实现邮箱格式校验 - 触发条件设置为 `blur`(焦点离开时校验) 3. **表单整体校验**: - 通过 `$refs.dynamicFormRef.validate()` 触发表单验证 - 自动处理所有字段(固定+动态)的校验状态 4. **UI/UX 优化**: - 删除按钮仅显示在可删除的字段上 - 保留至少一个动态字段的约束 - 使用 Element UI 的反馈消息提升体验 #### 4. 样式优化(可选) ```css <style scoped> .dynamic-item { position: relative; padding-right: 40px; } .el-button--danger { position: absolute; right: 0; top: 0; } </style> ``` #### 5. 常见问题解决 1. **校验不触发**: - 确保 `prop` 路径格式正确:`emails.0.value` - 检查动态字段是否包含在 `formRules` 或独立规则中 2. **删除后校验残留**: - 使用 `this.$refs.dynamicFormRef.clearValidate()` 清除校验状态 ```javascript removeEmail(index) { this.dynamicForm.emails.splice(index, 1); this.$nextTick(() => { this.$refs.dynamicFormRef.clearValidate(); }); } ``` 3. **复杂嵌套校验**: ```javascript // 多层级对象校验 :prop="`contacts.${index}.phone.value`" // 数组直接校验 :prop="`phones[${index}]`" ``` >[!TIP] >使用 Vue Devtools 实时检查表单数据结构和校验状态,能显著提高调试效率[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值