vue 封装动态生成form表单
动态生成 form 表单组件
<template>
<div class="form">
<el-form
ref="formDom"
:model="formData"
:inline="inline"
:label-width="labelWidth"
:label-position="labelPosition"
>
<el-form-item
v-for="item in formConfig"
:key="item.model"
:label="item.label"
:label-width="item.labelWidth||'100'"
>
<el-input
v-if="item.type === 'input'"
v-model="formData[item.model]"
:type="item.inputType ? item.inputType : 'text'"
:placeholder="`请输入${item.label}`"
clearable
/>
<el-date-picker
v-if="item.type === 'daterange'"
v-model="formData[item.model]"
type="daterange"
format="yyyy-MM-dd"
:style="`
width: ${item.width ? item.width : 200}px
`"
:placeholder="`请选择${item.label}`"
@on-change="setDateRange(formData[item.model], item.model)"
/>
<el-select
v-if="item.type === 'select'"
v-model="formData[item.model]"
clearable
:placeholder="`请选择${item.label}`"
:multiple="item.multiple"
:filterable="item.filterable"
:max-tag-count="item.max_tag_count"
style="width:100%;"
>
<el-option
v-for="data in item.list"
:key="getSelectKeys(data, 'key')"
:label="getSelectKeys(data, 'value')"
:value="getSelectKeys(data, 'key')"
>
{{ getSelectKeys(data, "value") }}
</el-option>
</el-select>
<slot name="item" />
<el-button
v-if="item.type === 'confirm'"
type="primary"
:loading="item.isSearching"
@click="submit"
>
查询
</el-button>
<el-button
v-if="item.type === 'reset'"
type="primary"
@click="reset"
>
重置
</el-button>
<slot name="button" />
</el-form-item>
<slot name="form" />
</el-form>
</div>
</template>
<script>
export default {
name: 'CommonForm',
props: {
// 表单项是否行内显示
inline: {
type: Boolean,
default: true,
},
// 表单项配置
formConfig: {
type: Array,
default: () => []
},
// 表单项数据
formDataInit: {
type: Object,
default: () => {}
},
// 表单标签宽度
labelWidth: {
type: [Number,String],
default: '100',
},
// 表单标签位置,默认左侧
labelPosition: {
type: String,
default: 'left',
},
},
data() {
return {
formData: this.formDataInit,
selectKeys: []
};
},
mounted() {
// 初始化设置formdata项的开始时间和结束时间
this.formConfig
.filter(item => item.type === 'daterange')
.map(item => {
this.setDateRange(this.formData[item.model], item.model);
});
},
methods: {
getSelectKeys(obj, type) {
const key = Object.keys(obj);
return type === 'key' ? obj[key[0]] : obj[key[1]];
},
// 选取日期后赋给 form 对应属性名
setDateRange(date, model) {
this.formData[`${model}_start`] = date[0];
this.formData[`${model}_stop`] = date[1];
},
submit() {
this.$emit('submit');
},
reset() {
this.$refs.formDom.resetFields();
}
},
};
</script>
<style lang="less" scoped>
.form {
display: flex;
justify-content: flex-start;
flex-wrap: wrap;
.ivu-form-item {
min-width: 19%;
margin-bottom: 4px;
/deep/ .ivu-input-with-suffix {
padding: 4px;
}
}
/deep/ .ivu-form {
color: #333;
width: 100%;
}
}
@media screen and (max-width: 1300px){
.ivu-form-item {
width: 23%;
};
}
</style>
调用
<!-- 引用 CommonForm -->
<template>
<div v-cloak>
<CommonForm
:formDataInit="formDataInit"
:form-config="formConfig"
:label-width="70"
@submit="getList"
/>
</div>
</template>
<script>
...
data() {
return {
isSearching: false, // // 是否查询中
formConfig: [ // 表单配置
{ model: 'id', label: 'id', type: 'input'},
{ model: 'ids', label: '项目id', type: 'input'},
{
model: 'status', // 搜索项参数名,和 form 中的参数名一致
label: '状态', // 搜索项标签,即左侧文案
type: 'select', // 搜索项类型
multiple: true, // 是否支持多选
max_tag_count: 1, // 多选时最多显示多少个 tag
list: [{
value: '选项1',
label: '黄金糕'
}, {
value: '选项2',
label: '双皮奶'
}, {
value: '选项3',
label: '蚵仔煎'
}, {
value: '选项4',
label: '龙须面'
}, {
value: '选项5',
label: '北京烤鸭'
}], // select选择项列表
},
{
model: 'time', // 搜索项参数名,和 form 中的参数名一致
label: '开始时间', // 搜索项标签,即左侧文案
type: 'daterange', // 搜索项类型
},
{
model: 'confirm', // 确认按钮
text: '查询', // 按钮文案
type: 'confirm',
label: '',
labelWidth: 0,
isSearching: this.isSearching
},
],
formDataInit: { // 检索参数
id: '',
page_number: 1,
page_size: 10,
time: [],
},
};
},
};
</script>