el-form表单封装
缘由
系统页面大部分为
form+tabel的结构,系统复杂起来代码就看起来非常冗余,要修改起来也很麻烦,于是决定将表单封装起来。
结构
业务与逻辑区分
- 新建
const.js文件,处理表单逻辑
- 新建
配置化
json对象化配置表单属性
扩展&特殊处理
- 配置
slot插槽
- 配置
开始
html
<template>
<el-form
ref="form"
:id="formConfig.id"
:class="formConfig.className"
:label-width="formConfig.labelWidth || '100px'"
:size="formConfig.size || 'medium'"
:rules="formConfig.rules"
:model="formData"
>
<template
v-for="(item, index) in getConfigList()"
:key="index"
>
<el-form-item
:prop="item.value"
:label="item.label"
:label-width="item.labelWidth"
:class="item.className"
>
<!-- solt -->
<template v-if="item.type === 'slot'">
<slot :name="'form-' + item.value" />
</template>
<component
:is="item.type"
v-model="formData[item.value]"
:type="item.dataType"
:picker-options="item.timePickerOptions"
:clearable="item.clearable"
:disabled="item.disabled"
:start-placeholder="item.startPlaceholder"
:end-placeholder="item.endPlaceholder"
:range-separator="item.rangeSeparator || '-'"
:filterable="item.filterable"
:multiple="item.multiple"
:collapse-tags="item.collapseTags"
default-first-option
:allow-create="item.allowCreate"
:no-data-text="item.noDataText || ''"
:placeholder="getPlaceholder(item)"
:value-format="item.valueFormat"
:format="item.valueFormat"
:style="{ width: item.width || '100%' }"
:maxlength="item.maxLength"
:autosize="item.autosize || { minRows: 2, maxRows: 10 }"
@click="handleEvent(item.event, formData[item.value], 'click')"
@change="handleEvent(item.event, formData[item.value], 'change')"
@input="handleEvent(item.event, formData[item.value], 'input')"
@blur="handleEvent(item.event, formData[item.value], 'blur')"
>
<template v-if="item.type === 'el-select'">
<el-option
v-for="(childItem, childIndex) in listTypeInfo[item.list]"
:key="`${childItem.value}${childIndex}`"
:label="childItem.label"
:value="childItem.value"
></el-option>
</template>
{{ item.title || '' }}
</component>
</el-form-item>
</template>
</el-form>
</template>
<script>
export default {
name: 'FormItemComp',
data() {
return { formData: {} };
},
props: {
// 表单配置项
formConfig: {
type: Object,
default: () => {},
},
// 表单数据
data: { type: Object },
// 下拉选项list
listTypeInfo: { type: Object },
// ref
refObj: { type: Object },
},
watch: {
data: {
handler(val) {
if (!val) return;
this.formData = val;
// 将form实例返回到父级
this.$emit('update:refObj', this.$refs.form);
},
deep: true,
},
},
mounted() {
this.formData = this.data;
// 将form实例返回到父级
this.$emit('update:refObj', this.$refs.form);
},
methods: {
// 获取字段列表
getConfigList() {
return this.formConfig.fieldList.filter(
(item) => !Object.prototype.hasOwnProperty.call(item, 'show')
|| (Object.prototype.hasOwnProperty.call(item, 'show') && item.show),
);
},
// 得到placeholder的显示
getPlaceholder(row) {
let placeholder;
const types = ['el-select', 'el-date-picker'];
if (row.type === 'el-input') {
placeholder = `请输入${row.placeholder || ''}`;
} else if (types.includes(row.type)) {
placeholder = `请选择${row.placeholder || ''}`;
} else {
placeholder = row.label;
}
return placeholder;
},
// 表单事件派发
handleEvent(event, data, type) {
this.$emit('handleEvent', { event, data, type });
},
},
};
</script>使用
js
// const.js
export const FormJson = {
id: 'form',
rules: {},
labelWidth: '100px',
size: 'mini',
className: 'el-form-component',
fieldList: [
{
label: '名称:',
value: 'name',
type: 'el-select',
clearable: true,
list: 'nameList',
},
{
label: '来源:',
value: 'source',
type: 'el-select',
clearable: true,
list: 'formSelect1',
},
{
label: '主体:',
value: 'subject',
type: 'el-input',
},
{
label: '分类:',
value: 'nature',
type: 'el-select',
clearable: true,
list: 'formSelect2',
},
{
label: '日期:',
value: 'date',
type: 'el-date-picker',
dataType: 'daterange',
valueFormat: 'yyyy-MM-dd',
startPlaceholder: '开始日期',
endPlaceholder: '结束日期',
rangeSeparator: '至',
clearable: true,
},
{
label: '状态:',
value: 'status',
type: 'el-select',
clearable: true,
list: 'projectStatus',
},
// slot插槽
{
label: '',
value: 'btn',
type: 'slot',
colWidth: 18,
className: 'text-right',
},
],
};html
<template>
<FormItemComp
:formConfig="FormJson"
:refObj.sync="formRef"
:data="formData"
:listTypeInfo="listTypeInfo"
@handleEvent="handleEvent"
>
<template slot="form-btn">
<div>
<el-button type="search" @click="">查询</el-button>
<el-button type="reset" @click="">重置</el-button>
</div>
</template>
</FormItemComp>
</template>
<script>
import FormItemComp from './FormItemComp'
import { FormJson } from './const.js'
export default {
data(){
return {
FormJson,
formRef: null, // form ref
formData: {
name: '',
source: '',
subject: '',
nature: '',
date: '',
status: '',
},
// el-select选项
listTypeInfo: {
formSelect1:[],
formSelect2:[],
projectStatus:[],
nameList:[],
}
}
},
components: { FormItemComp },
methods: {
// 表单的相关事件
handleEvent(val) {
}
}
</script>