vue+element,form循环嵌套表单 、动态添加表单、嵌套表单自定义校验规则

本文介绍如何在Vue中实现动态表单的增删及嵌套表单的自定义校验规则。通过v-for循环创建表单元素,并绑定prop属性进行表单验证。同时,详细解释了如何设置自定义校验函数,确保表单内容的有效性和唯一性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文发布链接:https://juejin.cn/post/7181752966611730492

需求:

  • 可点击新增,自动添加表单。(这个不难v-for即可)
  • 可自定义方法校验添加的表单内容。(需要掌握element组件的规则,本人没有熟读官网,碰壁好多次才整理出来这篇文章。重要的事说3遍:看官网看官网看官网

效果图:
image.png

动态嵌套校验的难点主要是如何绑定prop属性,自定义方法的难点主要是如何在嵌套的基础上设置自定义方法以及如何将v-for的索引传入校验

Form-Item Attributes

参数说明类型可选值默认值
prop表单域 model 字段,在使用 validate、resetFields 方法的情况下,该属性是必填的string传入 Form 组件的 model 中的字段

可看到,这里prop是传入 Form 组件的 model 中的字段。需要注意的是,prop字段是有相对路径的,而不是随意的一个字段名就可以,需要按照element的格式传入相应的字段

form循环嵌套表单

参考官网的“动态增减表单项”绑定prop属性,动态增减可以直接照搬这个示例(官网就是这么强大,你想要的都有)

image.png

image.png

一级嵌套

循环:<div v-for="(work,i) in formdata.jobList" :key="i">
prop绑定::prop="`jobList[${i}].jobContent`"
规则绑定::rules="[{ required: true, message: '作业内容不能为空', trigger: 'blur' }]"

注:prop不能直接使用work.jobContent
jobList[${i}].jobContent是elementui规定的格式,渲染后的结果为jobList[i].jobContent

二级嵌套

循环:<div style="padding: 10px 20px" v-for="(item,j) in work.specialJobList" :key="j">
prop绑定::prop="`jobList[${i}].specialJobList[${j}].type`"
规则绑定::rules="[{ required: true, message: '请选择特殊作业', trigger: 'blur' }]"

动态添加表单

很显然,动态添加只需要改变v-for的数组即可,新增作业活动如下:

<div class="addBox" type="primary" size="mini" @click="addWorkActivity()>
    <img src="static/img/u15.svg" alt="" class="addIcon" ">
    <span class="operate" >新增作业活动</span>
</div>
// 新增作业活动
addWorkActivity(){
    let obj = {jobContent:"",specialJobList:[{type:"",itemsList:[]}]};
    if(!Array.isArray(this.formdata.jobList)){
        this.formdata.jobList = [];
    }
    this.formdata.jobList.push(obj);
},

嵌套中的表单自定义校验规则

这里需要校验作业内容不能为空,且作业内容不能重复,这里需要将修改的内容和动态的数组对比还需要调服务判断数据库中有无相同的内容来校验,就不能使用简单的校验,需要自定义校验validator

绑定自定义函数,使用el-form-itemrules属性的validator。自定义校验可参考官网的自定义校验规则

image.png

image.png

这里写在el-form-item上与其类似,由于是动态绑定的prop属性,所以这里用el-formrules属性很难校验

循环:<div v-for="(work,i) in formdata.jobList" :key="i">
prop绑定::prop="`jobList[${i}].jobContent`"
规则绑定::rules="[{ required: true, validator:(rule, value, callback)=> checkContent(rule, value, callback,i), trigger: ['blur', 'change']}]"
// 表单校验内容是否重复
async checkContent(rule, value, callback,index){
    if (!value) {
        callback(new Error("作业内容不能为空!"));
    } else {
        let isRepeat = false;// 默认不重复
        for(let i = 0; i < this.formdata.jobList.length; i++){
            if (this.formdata.jobList[i].jobContent == value && i !== index){
                isRepeat = true;
                callback(new Error(`已存在相同的作业内容,请重新输入!`));
                return;
            }
        }
        if(!isRepeat){
            // 页面没有重复时 调服务判断数据库中是否有重复
            let params = {
                jobContent:value,
                id:this.formdata.id
            }
            const res = await serviceValid();// 调用服务校验
            if (res.data.body === "已有重复作业活动") {
                callback(new Error(`已存在相同的作业内容,请重新输入!`));
            }
        }
        callback();
    }
}

注:这里使用 validator:(rule, value, callback)=> checkContent(rule, value, callback,i)主要是为了获得当前索引,如果不需要,直接绑定函数名即可:validator:checkContent

checkContent(rule, value, callback){……}

<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、付费专栏及课程。

余额充值