el-form表单封装
# 缘由
系统页面大部分为
form+tabel
的结构,系统复杂起来代码就看起来非常冗余,要修改起来也很麻烦,于是决定将表单封装起来。
# 结构
业务与逻辑区分
- 新建
const.js
文件,处理表单逻辑
- 新建
配置化
json
对象化配置表单属性
扩展&特殊处理
- 配置
slot
插槽
- 配置
# 开始
<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>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# 使用
// 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',
},
],
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<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>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
上次更新: 2022/09/06, 16:01:35