form-render.vue
5.25 KB
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
131
132
133
134
135
136
137
138
139
140
141
142
143
<template>
<!-- 在row上使用flex,防止表单组件大小不一导致错位 -->
<component :is="rowComponent" class="eagle-form__flex-wrap">
<template v-for="(item, index) in list">
<!-- 表单项有设置分组时 -->
<component :is="colComponent" v-if="item.group && item.list" :key="index"
:span="type === 'div' ? undefined : item.group.span || 24" :style="{ width: type === 'div' ? '100%' : undefined }"
>
<component :is="rowComponent" class="eagle-form__flex-wrap" :class="groupClass || 'eagle-form__group'">
<!-- 表单分组标题 -->
<component :is="rowComponent" :class="titleClass || 'eagle-form__group-title'" v-if="item.group.title" style="width: 100%;">
{{ item.group.title || item.group }}
</component>
<!-- 递归本组件 -->
<form-render :title-class="titleClass" :item-class="itemClass" :content-class="contentClass" :group-class="groupClass"
:class="contentClass || 'eagle-form__group-content'" :list="item.list" :value="value"
:model="itemKey ? model[itemKey] || {} : model" :itemKey="item.group.key" :type="type"
@item-change="onItemChange" @form-item-change="onFormItemChange" @item-update="onItemUpdate"
:span="type === 'div' ? undefined : span * (24 / (item.group.span || 24))"
></form-render>
</component>
</component>
<!-- 正常无分组表单项 -->
<component :is="colComponent" v-else :span="type === 'div' ? undefined : item.span || span" :key="index"
:style="{ width: type === 'div' && item.style && item.style.width.includes('%') ? item.style.width : undefined, paddingRight: '10px' }"
>
<el-form-item :label="item.label" :label-width="item.labelWidth" :prop="item.fullKey" :rules="item.rules" :class="itemClass || 'eagle-form__item'">
<!-- 自定义组件 -->
<dynamic-render v-if="typeof item.type === 'function'"
:render="item.type($createElement, { model: value, config: {
props: { ...item.props, value: itemValue(item) },
style: item.style || { maxWidth: '100%' },
on: {
...bindItemEvent(item),
input: v => onInput({ value: v, item })
}
} })"
></dynamic-render>
<component v-else :is="item.type" :value="itemValue(item)" @input="v => onInput({ value: v, item })"
v-on="bindItemEvent(item)" v-bind="item.props" :style="item.style || { maxWidth: '100%' }"
></component>
</el-form-item>
</component>
</template>
</component>
</template>
<script>
import DynamicRender from './dynamic-render';
export default {
name: 'form-render',
components: { DynamicRender },
props: {
list: Array,
model: Object,
value: Object,
itemKey: String,
titleClass: String,
contentClass: String,
itemClass: String,
groupClass: String,
type: String,
span: Number,
},
computed: {
rowComponent() {
return this.type === 'div' ? 'div' : 'el-row';
},
colComponent() {
return this.type === 'div' ? 'div' : 'el-col';
},
},
methods: {
/**
* @description 根据表单项的key查询该值
* @param {Object} item 表单项配置
* @returns {Any} 返回值
*/
itemValue(item) {
if (this.itemKey) { // 如果存在itemKey,即当前项位于嵌套分组内,查询分组名下对应key的值
const groupItem = this.model[this.itemKey] || {};
return groupItem[item.key];
} else { // 否则即意味着不在分组内,直接查询model下对应key的值
return this.model[item.key];
}
},
/**
* @description 组件有值输入时的事件
* @param {Object} data { value => 组件值; item => 表单项配置 }
*/
onInput({ value, item }) {
if (this.itemKey) {
this.$emit('item-change', { [this.itemKey]: { ...this.model[this.itemKey], [item.key]: value } });
} else {
this.$emit('item-change', { [item.key]: value });
}
this.$emit('form-item-change', { [item.fullKey]: value });
},
/**
* @description 当表单项有改动时的事件
* @param {Any} 表单项值
*/
onItemChange(value) {
if (this.itemKey) {
this.$emit('item-change', { [this.itemKey]: { ...this.model[this.itemKey], ...value } });
} else {
this.$emit('item-change', value);
}
},
/**
* @description 当表单项校验值有改动时的事件
* @param {Any} 表单项校验值
*/
onFormItemChange(value) {
this.$emit('form-item-change', value);
},
/**
* @description 当表单项有手动更新时的事件
* @param {Any} 表单项值
*/
onItemUpdate(value) {
this.$emit('item-update', value);
},
/**
* @description 绑定表单项事件
* @param {Object} item 表单项配置
* @returns {Function} 事件函数
*/
bindItemEvent(item) {
if (item.on) {
if (typeof item.on === 'function') {
return item.on({ model: this.value, update: e => this.$emit('item-update', e) });
} else {
return item.on
}
} else {
return undefined
}
},
}
}
</script>