前言
在我们的日常开发中,表单需求非常常见,可能会碰到一些比较复杂的情况,我们可以参考下面循环表单的实现得到一丝丝启发~
一、先看看效果
二、循环表单的实现
其实实现也比较简单,这里以elementUI的form表单为例。利用vue数据响应式原理,双向绑定,引用类型的特性实现。话不多说,直接上码。
<template>
<div class="content_style">
<div v-for="form in ruleForm" :key="form.key" class="all_content">
<el-button class="delete_class_form" type="text" @click="deleteForm(ruleForm, form.key)">删除</el-button>
<div class="form1_content">
<el-form
ref="ruleForm1"
class="form"
:model="form.ruleForm1"
label-width="100px"
>
<el-form-item label="清单名称" prop="name" :rules="rules.name">
<el-input v-model="form.ruleForm1.name"></el-input>
</el-form-item>
<el-form-item label="清单类型" prop="type">
<el-select v-model="form.ruleForm1.type" placeholder="请选择">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</el-form-item>
</el-form>
</div>
<div>
<div v-for="(item, j) in form.ruleForm2" :key="item.key" class="form2_content">
<el-form class="form" :ref="`ruleForm2-${item.key}`" :model="item" label-width="100px">
<el-button class="delete_class_form2" type="text" @click="deleteForm(form.ruleForm2, item.key)">删除</el-button>
<el-form-item :label="`活动名称${j+1}`" prop="name" :rules="rules.name">
<el-input v-model="item.name"></el-input>
</el-form-item>
<el-form-item label="活动类型" prop="type">
<el-select v-model="item.type" placeholder="请选择">
<el-option
v-for="val in options"
:key="val.value"
:label="val.label"
:value="val.value"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item v-for="(extra, k) in item.extraInfo" :key="extra.key" :label="`备注${k+1}`" :prop="`extraInfo.${k}.value`" :rules="rules.extraInfo">
<el-input v-model="extra.value"></el-input>
<el-button v-if="item.extraInfo.length !== 1" type="text" icon="el-icon-minus" class="delete_extra_class" @click="deleteForm(item.extraInfo, extra.key)"></el-button>
<el-button v-if="k === item.extraInfo.length-1" type="text" icon="el-icon-plus" class="add_extra_class" @click="addForm(item.extraInfo, 'extra')"></el-button>
</el-form-item>
</el-form>
</div>
<el-button plain type="text" icon="el-icon-plus" class="add_form2_class" @click="addForm(form.ruleForm2, 'form2')"></el-button>
</div>
</div>
<el-button plain type="text" icon="el-icon-plus" class="add_form_class" @click="addForm(ruleForm, 'form')"></el-button>
<div class="button_group">
<el-button type="primary" class="reset" size="small" @click="reset">重置</el-button>
<el-button type="primary" class="confirm" size="small" @click="confirm">确定</el-button>
</div>
</div>
</template>
export default {
data() {
return {
ruleForm: [this.getDefaultForm(new Date().getTime())],
options: [
{value: '1',label: '黄金糕'},
{value: '2',label: '双皮奶'},
{value: '3',label: '蚵仔煎'},
{value: '4',label: '龙须面'},
{value: '5',label: '北京烤鸭'}
],
rules: {
name: [{required: true, message: '名称必填', trigger: ['change', 'blur']}],
extraInfo: [{required: true, message: '备注必填', trigger: ['change', 'blur']}],
}
}
},
methods: {
getDefaultForm2(baseKey) {
return {
name: '',
type:'',
key: `${baseKey}-form2`,
extraInfo: [this.getDefaultExtra(baseKey)]
}
},
getDefaultExtra(baseKey) {
return {
value:'',
key: `${baseKey}-extra`
}
},
getDefaultForm(baseKey) {
return {
ruleForm1: {name: '', type: ''},
ruleForm2: [this.getDefaultForm2(baseKey)],
key: `${baseKey}-form1`
}
},
deleteForm(item, key) {
const index = item.findIndex(v => v.key === key)
if(index !== -1) {
item.splice(index, 1)
}
},
addForm(item, type) {
const baseKey = new Date().getTime()
const addMethod = {
extra: this.getDefaultExtra,
form: this.getDefaultForm,
form2: this.getDefaultForm2
}[type]
item.push(addMethod(baseKey))
},
reset() {
this.ruleForm = [this.getDefaultForm(new Date().getTime())];
},
confirm() {
this.$confirm('确定提交?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$message({
type: 'success',
message: '提交成功'
});
}).catch(() => {});
}
}
}
需要注意的是因为要涉及到增删改,所以需要给数组的每个对象设置一个key值,而且这个key在同一级数组中还要是唯一的,那么就可以利用时间戳来实现,或者es6新增的symbol来实现,方便后续的增删。而增删又用到了引用类型数据的特点,方法入参传过去的是引用地址,所以后续只要不是深拷贝,针对该参数的改变实际上都是针对同一个引用地址数据的改变。
同时还要注意的一点就是如果需要表单校验生效的话,需要保证每个表单的prop是正确的,不然后续校验就找不到对应的绑定变量了。
三、总结
复杂的循环表单的实现其实也不难,多看多思考就行了哈~ 可以参照demo,github链接:github.com/qiangguangl…
下期预告
针对以上的循环表单,其实涉及到了多个el-form,那么我们最后在提交表单的时候需要对表单都进行校验,但因为是for循环出来的,所以表单具体的ref我们也不知道有多少个,具体怎么校验就是下期的内容啦~
针对循环表单,我们如何全部校验呢?敬请期待~