背景:
公司有个‘美国行’的游学项目,在筹备阶段需要收集律师们的信息来办理邀请函签证等;之前一直用的三方信息收集工具,但是考虑到数据流失问题,最后决定自己搞个小程序来收集。
页面:
image.png等等等。。手机不好截图,截个后台的图~
开发过程:
一开始以为就是普通的表单,select radio input datepicker 来几波就能搞定。。。但是对接了需求后发现表单项是在是太多了,不但有的还有关联关系,如:婚姻状态选了已婚才会出现子女信息和配偶信息;而且子女信息等还可以添加多个。。。。
CALM DOWN
补单表单项多而且还有关联关系。。总不能一个个if搞简直太low。
于是决定处理下:
1.将各个不同交互项抽成组件
2.根据表单对象passData 的key 构造成新的带有配置项的 configObj
3.对表使用for操作,在configData 中 取 passData 对应key的配置进行渲染
成果:
主文件代码:
ps: template 部分只有82行,如果用component再来一层目测也就20行左右吧+
<Form ref="materialForm" :model="passData" label-position="top">
<div v-for="(val, key) in configObj" :key="key" v-if="!val.hide">
<FormItem class="form-item" :label="val.label" v-show="!val.stillHide" :required="val.required" :prop="key">
<p class="tips">{{val.tip}}</p>
<input
class="ivu-input"
v-if="val.type === 'text'"
v-model="passData[key]"
:name="key"
:data-vv-name="key"
v-validate="{required: !!val.required}"
/>
<textarea
class="ivu-input"
v-else-if="val.type === 'textarea'"
v-model="passData[key]"
:name="key"
:data-vv-name="key"
v-validate="{required: !!val.required}"
></textarea>
<Select
v-model="passData[key]"
v-else-if="val.type === 'radioSelect'"
v-validate="{required: !!val.required}"
:data-vv-name="key"
>
<option value="">--请选择--</option>
<Option v-for="item in val.list" :key="item" :value="item">{{item}}</Option>
</Select>
<p v-show="errorBags.has(`${key}`)" class="error">请填写{{val.label}}</p>
</FormItem>
<div v-if="val.showOption && val.ifOption !== undefined">
<div
v-for="(optItem, index) in val.ifOption.option"
:key="`${val.ifOption.key}_${index}`"
>
<FormItem
v-for="(optVal, optKey) in optItem"
:key="`${val.ifOption.key}_${index}_${optKey}`"
class="form-item"
:label="optVal.label"
:required="optVal.required"
:prop="optKey"
>
<p class="tips">{{optVal.tip}}</p>
<input
class="ivu-input"
v-if="optVal.type === 'text' || optVal.type === 'number'"
v-validate="{required: !!optVal.required}"
v-model="passData[val.ifOption.key][index][optKey]"
:data-vv-name="key"
:name="`${val.ifOption.key}_${index}_${optKey}`"
:type="optVal.type"
/>
<textarea
class="ivu-input"
v-else-if="optVal.type === 'textarea'"
v-validate="{required: !!optVal.required}"
v-model="passData[val.ifOption.key][index][optKey]"
:data-vv-name="key"
:name="`${val.ifOption.key}_${index}_${optKey}`"
></textarea>
<p v-show="errorBags.has(`${val.ifOption.key}_${index}_${optKey}`)" class="error">请填写{{optVal.label}}</p>
</FormItem>
</div>
</div>
</div>
</Form>
配置文件的一部分:
ps: 虽然配置文件有500+行😂,最好是后端返回模板
email: {
label: '邮箱',
type: 'text',
defaultVal: '无',
required: true
},
recipientName: {
label: '收件人姓名',
type: 'text',
required: true
},
recipientPhone: {
label: '收件人联系方式',
type: 'text',
required: true
},
recipientAddress: {
label: '收件人地址',
type: 'text',
required: true
},
// 家庭情况
homeAddress: {
label: '家庭住址',
type: 'text',
defaultVal: '无',
required: true
},
fatherStatus: {
label: '父亲',
type: 'radioSelect',
defaultVal: '健在',
required: true,
list: OPTIONS.peopleStatus,
ifOption: {
key: 'fatherInfo',
option: [{
name: {
label: '父亲姓名',
type: 'text',
required: true
},
birthTime: {
label: '父亲出生年月日',
type: 'text',
defaultVal: 'XXXX年XX月XX日',
required: true
},
birthPlace: {
label: '父亲出生地',
type: 'text',
required: true
},
workPlace: {
label: '父亲现地址(工作或者生活)',
tip: '如与您住在一起,请填写“家庭住址”',
type: 'text',
required: true
}
}]
}
},
以上。
路过的把你们的喜欢留一下啵~💗
网友评论