vue 封装动态生成form表单和table表格组件
背景项目中经常遇到新加功能和之前功能类似,结构不变,只是名称和值变化,因此将常用的form表单检索和table表格展示进行封装,有助于提高开发效率和统一样式风格。注:示例中使用iview框架,实际代码结构类似,供参考。动态生成 form 表单组件使用说明:引入文件并注册页面使用并传参,支持输入框、日期选择、下拉选择和查询按钮搜索项,搜索项后面可以通过插槽添加自定义内容组件暴露出的数据为 form
·
背景
项目中经常遇到新加功能和之前功能类似,结构不变,只是名称和值变化,因此将常用的form表单检索和table表格展示进行封装,有助于提高开发效率和统一样式风格。
注:示例中使用iview框架,实际代码结构类似,供参考。
动态生成 form 表单组件
使用说明:
- 引入文件并注册
- 页面使用并传参,支持输入框、日期选择、下拉选择和查询按钮搜索项,搜索项后面可以通过插槽添加自定义内容
- 组件暴露出的数据为 form 表单项最新数据
API:
form props
属性 | 说明 | 类型 | 默认值 |
---|---|---|---|
form | 表单项数据 | Object | {} |
formConfig | 表单项配置 | Array | [] |
inline | 表单项是否行内显示 | Boolean | true |
labelWidth | 表单标签宽度 | Number | 100 |
labelPosition | 表单标签位置 | String | left |
form events
事件名 | 说明 | 返回值 |
---|---|---|
submit | 点击查询按钮触发 | formData,最新表单数据 |
form组件代码:
<template>
<div class="form">
<i-form
ref="form"
:model="formData"
:inline="inline"
:label-width="labelWidth"
:label-position="labelPosition"
>
<i-form-item
v-for="item in formConfig"
:key="item.model"
:label="item.label"
:label-width="item.labelWidth"
>
<i-input
v-if="item.type === 'input'"
v-model="formData[item.model]"
:type="item.inputType ? item.inputType : 'text'"
clearable
/>
<i-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
`"
@on-change="setDateRange(formData[item.model], item.model)"
/>
<i-select
v-if="item.type === 'select'"
v-model="formData[item.model]"
clearable
placeholder="请选择"
:multiple="item.multiple"
:filterable="item.filterable"
:max-tag-count="item.max_tag_count"
style="width:100%;"
>
<i-option
v-for="data in item.list"
:key="getSelectKeys(data, 'key')"
:value="getSelectKeys(data, 'key')"
>
{{ getSelectKeys(data, "value") }}
</i-option>
</i-select>
<slot name="item" />
<i-button
v-if="item.type === 'confirm'"
type="primary"
:loading="item.isSearching"
@click="submit"
>
查询
</i-button>
<i-button
v-if="item.type === 'reset'"
type="primary"
@click="reset"
>
重置
</i-button>
<slot name="button" />
</i-form-item>
<slot name="form" />
</i-form>
</div>
</template>
<script>
export default {
name: 'CommonForm',
props: {
// 表单项是否行内显示
inline: {
type: Boolean,
default: true,
},
// 表单项配置
formConfig: {
type: Array,
default: () => []
},
// 表单项数据
form: {
type: Object,
default: () => {}
},
// 表单标签宽度
labelWidth: {
type: Number,
default: 100,
},
// 表单标签位置,默认左侧
labelPosition: {
type: String,
default: 'left',
},
},
data() {
return {
formData: this.form,
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.form.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>
form组件使用
<template>
<div v-cloak>
<CommonForm
:form="form"
:form-config="formConfig"
:label-width="70"
@submit="getList"
/>
</div>
</template>
<script>
...
data() {
return {
isSearching: false, // // 是否查询中
formConfig: [ // 表单配置
{ model: 'id', label: 'id', type: 'input'},
{
model: 'status', // 搜索项参数名,和 form 中的参数名一致
label: '状态', // 搜索项标签,即左侧文案
type: 'select', // 搜索项类型
multiple: true, // 是否支持多选
max_tag_count: 1, // 多选时最多显示多少个 tag
list: [], // select选择项列表
},
{
model: 'confirm', // 确认按钮
text: '查询', // 按钮文案
type: 'confirm',
label: '',
labelWidth: 0,
isSearching: this.isSearching
},
],
form: { // 检索参数
id: '',
page_number: 1,
page_size: 10,
time: [],
},
};
},
};
</script>
动态生成 table表格组件
使用说明:
- 引入文件并注册
- 页面使用并传参,支持插槽,每列使用template可往插槽注入内容,目前组件中已封装根据状态显示为不同颜色的tag标签
- 组件操作中,已封装查看和编辑功能
API:
table props
属性 | 说明 | 类型 | 默认值 |
---|---|---|---|
config | 表格项配置,包含表头数据和表格数据 | Object | {} |
editDisabled | 编辑为只读的条件配置项 | Object | {} |
editText | 编辑按钮文案 | String | 编辑 |
table events
事件名 | 说明 | 返回值 |
---|---|---|
edit | 点击编辑按钮触发 | {row-当前行数据,isEdit-是否可编辑} |
table组件:
<template>
<div class="table">
<i-table border :columns="config.header" :data="config.data">
<template
v-for="column in config.header"
:slot="column.slot ? column.slot : ''"
slot-scope="{row}"
>
<i-tag
v-if="row[column.slot] && row[column.slotName]"
:key="column.slot"
:color="
setStatusTagColor(
row[column.slot],
column.tagColorList,
column.slotDefaultColor
)
"
>
{{ row[column.slotName] }}
</i-tag>
<slot :name="column.slot ? column.slot : ''" v-bind="row"></slot>
</template>
<template slot-scope="{row}" slot="action">
<i-button type="primary" @click="edit(row, false)">查看</i-button>
<i-button
type="error"
:disabled="
editDisabled
&&
editDisabled.disabledList.includes(+row[editDisabled.disabledColumn])"
@click="edit(row, true)"
>
{{ editText }}
</i-button>
</template>
</i-table>
</div>
</template>
<script>
export default {
name: 'CommonTable',
props: {
// 表单配置项
config: {
type: Object,
default: () => {}
},
// 编辑为只读的条件配置项
editDisabled: {
type: Object,
default: () => {}
},
// 编辑按钮文案
editText: {
type: String,
default: '编辑'
},
},
methods: {
/*
* 计算表格中标签展示颜色
* @param {number|string} status 状态值
* @param {array} tagColorList 标签颜色组合项
* @param {string} defaultColor 不在标签颜色项时,默认标签颜色
* @return {string} 返回str格式:标签颜色值
*
*/
setStatusTagColor(status, tagColorList = [], defaultColor) {
const isExits = tagColorList.find(item => +item.status === +status);
return isExits ? isExits.color : defaultColor;
},
edit(row, isEdit) {
this.$emit('edit', row, isEdit);
}
},
};
</script>
table组件使用
<template>
<div v-cloak>
<CommonTable
:config="tableConfig"
:edit-disabled="editDisabledConfig"
@edit="edit"
/>
<i-page
show-total
:total="total"
:page-size="form.page_size"
@on-change="changepage"
/>
</div>
</template>
<script>
...
data() {
return {
tableConfig: {
header: [
{ title: '内容', key: 'name', tooltip: true },
{
title: '状态',
key: 'status',
slot: 'status', // 插槽名
slotName: 'status_name', // 展示的tag名称
tagColorList: [ // tag标签颜色集合
{ status: 1, color: 'red' },
{ status: 2, color: 'blue' },
],
slotDefaultColor: 'red', // 不在tag标签颜色集合时,默认颜色
},
{ title: '操作', key: 'action', slot: 'action', fixed: 'right' }
],
// 表格数据,一般从接口获取
data: [],
},
// 不可编辑条件
editDisabledConfig: {
disabledList: [120, 140], // 不可编辑数据集合
disabledColumn: 'status', // 根据此列判断是否可编辑
},
// 总条数
total: 0
};
},
};
</script>
更多推荐
已为社区贡献2条内容
所有评论(0)