最近做的项目中出现了多模块多表单的功能,考虑到大量表单页、样式和字典项维护开发维护起来都比较恶心,所以决定采用数据配置的形式做动态表单,网上找了一下没有看到符合我需求的可复用的组件,所以使用vue , element自己写了一个组件,后面开发表单直接通过操作增加配置项,非常方便, 下面直接上代码:
这里数据均为改造后数据,先看效果:
1,这里只写了文本框、选择器、分组选择器、计数器,上传组件,有需要其他表单功能的直接自己往里加吧
<el-form ref="form" :model="form" label-width="100px">
<el-form-item v-for="(item, index) in formItems" :label="item.label" :prop="item.prop"
:rules="item.rules">
<el-input v-if="item.type === 'input'" :class="item.class" v-model="item.value" :placeholder="item.placeholder"></el-input>
<el-select v-else-if="item.type === 'select'" :class="item.class" v-model="item.value" :placeholder="item.placeholder">
<el-option-group v-show="item.isGroup" v-for="group in item.options" :key="group.label"
:label="group.label">
<el-option v-for="option in group.options" :label="option.label"
:value="option.value"></el-option>
</el-option-group>
<el-option v-show="!item.isGroup" v-for="option in item.options" :label="option.label"
:value="option.value"></el-option>
</el-select>
<el-input-number v-else-if="item.type === 'number'" controls-position="right"
:class="item.class" :min="item.min" :max="item.max" v-model="item.value"></el-input-number>
<upload-file v-else-if="item.type === 'upload'" @updateFilePath="updateFilePath"/>
</el-form-item>
</el-form>
2,数据由表单配置管理界面配置的,这里在js展示部分数据
const formConfig = {
bj: [
{
type: 'input', //表单类型
label: '文本框:',
prop: 'batchName',
model: 'batchName',
value: '',
class: 'fromItemValue', //自定义样式
placeholder: '请输入文本框',
rules: [{required: true, message: '请输入文本框', trigger: 'blur'},
{max: 50, message: '最大50个字符', trigger: 'blur'}] //表单项验证
},
{
type: 'select',
label: '选择器:',
prop: 'language',
model: 'language',
value: '',
class: 'fromItemValue',
placeholder: '请选择选择器',
options:[
{label: "孙悟空", value: "1"},
{label: "猪", value: "2"},
{label: "马", value: "3"}
],
rules: [{ required: true, message: '请选择选择器', trigger: 'change' }]
},
{
type: 'select',
label: '分组选择器:',
prop: 'markxf',
model: 'markxf',
value: '',
class: 'fromItemValue',
placeholder: '请选择分组选择器',
isGroup: true,
options:[{
label: '免费',
options:[
{label: "花言巧语", value:"0"}
]
},{
label: '收费',
options:[
{label: "郭德刚", value:"1"},
{label: "林志玲", value:"2"}
]
}],
rules: [{ required: true, message: '请选择分组选择器', trigger: 'change' }]
},
{
type: 'select',
label: '选择器1:',
prop: 'formxgs',
model: 'formxgs',
value: '',
class: 'fromItemValue',
placeholder: '请选择选择器1',
options:[
{label: "GP", value: "1"},
{label: "GL" , value:"2"},
{label: "GD" , value:"3"}
],
rules: [{ required: true, message: '请选择选择器1', trigger: 'change' }]
},
{
type: 'select',
label: '选择器2:',
prop: 'samrxcy',
model: 'samrxcy',
value: '',
class: 'fromItemValue',
placeholder: '请选择选择器2',
options:[
{label: "ddddd", value: "1"},
{label: "eeeee" , value:"2"}
],
rules: [{ required: true, message: '请选择选择器2', trigger: 'change' }]
},
{
type: 'number',
label: '计数器1:',
prop: 'volxyy',
model: 'volxyy',
class: 'fromItemValue',
min: 0,
max: 100,
value: 50,
rules: []
},
{
type: 'number',
label: '计数器2:',
prop: 'pitxdd',
model: 'pitxdd',
class: 'fromItemValue',
min: 0,
max: 100,
value: 50,
rules: []
},
{
type: 'number',
label: '计数器3:',
prop: 'speed',
model: 'speed',
class: 'fromItemValue',
min: 0,
max: 100,
value:50,
rules: []
},
{
type: 'upload',
label: '导入文件:',
model: 'filePath',
value:[]
}
],
sh: [
{
type: 'input',
label: 'markXA:',
prop: 'batchName',
model: 'batchName',
value: '',
class: 'fromItemValue',
placeholder: '请输入markXA',
rules: [{required: true, message: '请输入markXA', trigger: 'blur'},
{max: 50, message: '最大50个字符', trigger: 'blur'}]
},
{
type: 'select',
label: 'markXF:',
prop: 'markxf',
model: 'markxf',
value: '',
class: 'fromItemValue',
placeholder: '请选择markXF',
options:[
{label: "静一", value:"1"},
{label: "静琪", value:"2"},
{label: "静欢", value:"3"},
{label: "静萱", value:"4"}
],
rules: [{ required: true, message: '请选择markXF', trigger: 'change' }]
},
{
type: 'select',
label: 'markXGS:',
prop: 'formxgs',
model: 'formxgs',
value: '',
class: 'fromItemValue',
placeholder: '请选择markXGS',
options:[
{label: "bh", value: "1"},
{label: "gg" , value:"2"},
{label: "hh" , value:"3"}
],
rules: [{ required: true, message: '请选择markXGS', trigger: 'change' }]
},
{
type: 'number',
label: 'markXYY:',
prop: 'volxyy',
model: 'volxyy',
class: 'fromItemValue',
min: 0,
max: 10,
value: 0,
rules: []
},
{
type: 'number',
label: 'markXDD:',
prop: 'pitxdd',
model: 'pitxdd',
class: 'fromItemValue',
min: 5,
max: 10,
value: 5,
rules: []
},
{
type: 'number',
label: 'markXYS:',
prop: 'apc',
model: 'apc',
class: 'fromItemValue',
min: 0,
max: 100,
value: 50,
rules: []
},
{
type: 'number',
label: 'markXYS:',
prop: 'speed',
model: 'speed',
class: 'fromItemValue',
min: 0,
max: 200,
value: 100,
rules: []
},
{
type: 'upload',
label: '导入文件:',
model: 'filePath',
value: []
}
]
}
//fromConfig.js
// 获取配置
function getConfig(target) {
let fc;
switch (target) {
case 'bj':
fc = formConfig.bj;
break;
case 'sh':
fc = formConfig.sh;
break;
}
let form = {};
// 获取表单字段和初始化数据
for (let item of fc) {
form[item.model] = item.defaultValue;
}
return {
'formItems': fc,
'form': form
}
}
export default {
getConfig
}