目的:不想重复书写表单的form ui,表单只需要传入数据即可展示、操作
// view代码块 代码只是数据遍历绑定展示
// 唯一遇到的问题是我之前想实现类似react中组件参数传递的拓展方式(...props),想着固定参数不可确定性太多后发现Vue支持的v-bind="$attrs"是一样的,就拿出来打印了下发现居然就是个对象那我直接拓展下它的属性不就好了。 我的问题迎刃而解了。这里没有加事件属性,后续使用的化可以加同步Vue支持的v-on="$listeners"
<template>
<el-form class="el-form-ui" :model="form" :label-width="labelWidth" :rules="rules" ref="FormRef" :inline="true">
<el-row :gutter="gutter" type="flex" :justify="justify" class="flex-wrap">
<el-col :span="formItem.span" v-for="formItem in formData" :key="formItem.key">
<el-form-item :label="formItem.label" :prop="formItem.name" :style="{ '--labelWidth': labelWidth }">
<component :is="formItem.component" v-model="form[formItem.name]" v-bind="{ ...$attrs, ...formItem.props }">
<template v-if="formItem.childComponent">
<component :is="formItem.childComponent" v-for="option in formItem.options" :key="option.key"
v-bind="{ ...option }" />
</template>
</component>
</el-form-item>
</el-col>
<slot name="option">
<el-col :span="1" :offset="1">
<el-form-item>
<el-button type="primary" @click="onSubmit">查询</el-button>
</el-form-item>
</el-col>
</slot>
</el-row>
</el-form>
</template>
现在是数据(这里只展示我的data数据了)
// 数据结构也很简单
/*
name: 'checkboxGroup', 很重要作为表单数据中绑定值的key
key: 'checkboxGroup', 用于页面遍历绑定可查看上文view结构
label: 'checkbox选择', 参考form-item中的参数
span: 6, 当前项在行中占据的内容(默认24) 参考el-col
component: 'el-checkbox-group', component中is绑定的组件即当前项渲染的表单类型
props:{ placeholder: '请输入姓名', clearable: true } 同步表单中的props属性,参数详见表单项的Attributes()[elementUi表单配置](https://element.eleme.cn/#/zh-CN/component/form)
childComponent: 'el-checkbox', 子component的绑定项(渲染组件下的选项、如:el-select、radioGroup、checkboxGroup等组件的options)
options: [{ label: '启用', name: 'type', key: 'city' }, { label: '封存', name: 'type', key: 'city1' }] childComponent中渲染的optios数组
*/
data(){
retutn{
formData: [
{
name: 'name',
key: 'name',
label: '姓名',
component: 'el-input',
span: 6,
props: { placeholder: '请输入姓名', clearable: true }
},
{
name: 'account',
key: 'account',
label: '姓名',
component: 'el-input',
span: 6,
props: { placeholder: '请输入姓名', clearable: true }
},
{
name: 'org',
key: 'org',
label: '职位',
span: 6,
component: 'el-select',
props: { placeholder: '请选择职位' },
childComponent: 'el-option',
options: [{ label: '职位1', value: 1 }, { label: '职位2', value: 0 }]
},
{
name: 'date',
key: 'date',
span: 6,
label: '日期选择',
component: 'el-date-picker',
props: { placeholder: '选择时间' }
},
{
name: 'time',
key: 'time',
span: 6,
label: '时间选择',
component: 'el-time-picker',
props: { placeholder: '选择时间' }
},
{
name: 'switch',
key: 'switch',
label: 'switch',
span: 6,
component: 'el-switch'
},
{
name: 'radioGroup',
key: 'radioGroup',
label: 'radio选择',
span: 6,
component: 'el-radio-group',
childComponent: 'el-radio',
options: [{ label: '启用' }, { label: '封存' }]
},
{
name: 'checkboxGroup',
key: 'checkboxGroup',
label: 'checkbox选择',
span: 6,
component: 'el-checkbox-group',
childComponent: 'el-checkbox',
options: [{ label: '启用', name: 'type', key: 'city' }, { label: '封存', name: 'type', key: 'city1' }]
},
{
name: 'selectTree',
key: 'selectTree',
label: 'tree选择',
span: 6,
component: SelectTree,
props: {
options: [{ id: '-1', parentId: '-1', level: 0, name: '根组织' },
{
id: '1',
parentId: '-1',
level: 0,
name: '根组织1',
children: [{
id: '2', parentId: '1', level: 0, name: '根组织2'
}]
}]
}
}
]
}
}
beforeMount() {
this.initFormModel() //这里是对于el-form中绑定model的处理,为了阻止太多的参数传入组件,毕竟form的可以可以依赖formData数据结构和prop
},
methods: {
initFormModel() {
this.formData.forEach(element => {
if (element.key === 'checkboxGroup') { // 这里是为了解决checkboxGroup必须要有一个默认值否则会报错
this.$set(this.form, element.key, [])
}
});
}
}
<!--存在自定义样式的原因是为了让col项自动换行,同时el-form-item内容撑开,计算el-form-item__content实际大小-->
.el-form-ui {
/deep/.flex-wrap {
flex-wrap: wrap;
flex-direction: row;
}
/deep/.el-col {
.el-form-item {
width: 100%;
}
.el-form-item__content {
width: calc(100% - var(--labelWidth)); // 这里修改时主要labelWidth变量是view中style里定义的
}
}
}
结束了,接下来就是使用。自定义组件也支持在模拟数据selectTree中存在,使用时直接**import SelectTree from ‘@/components/SelectTree.vue’**导入即可不需要在components注册