前端最常用的组件表单,每次写表单的时候都要区布局,封装后不要再写布局dom,只需要写一下配置文件即可生成表单。自用封装使用,目前还并不完善,存在一些bug,有需要的小伙伴可以参考,也希望大家评论、点赞!共同学习。

<EZForm label-width="90px"
label-position="top"
v-loading="sdata.isLoading"
:rules="formRules"
:model="form"
ref="formRef"
:settings="formSetting">
<-- slot 渲染-->
<template v-slot:permission>
<el-tree ref="treeRef" :data="menuTreeData" node-key="value" show-checkbox @check="onPermissionChange"></el-tree>
</template>
</EZForm>
import {defineComponent, reactive, computed, onBeforeMount, ref, nextTick} from 'vue'
export default defineComponent({
name: "EditRole",
setup() {
let menuTreeData = ref([]);
let treeRef = ref([]);
const formRef = ref();
const sdata = reactive({
visible: false,
isLoading: false,
isEdit: false
});
const form= reactive({
name:'',
permission:[],
desc:'',
status:1,
});
const formRules = reactive({
name:{required:true, message: '请输入', trigger: 'blur'},
desc:{required:true, message: '请输入', trigger: 'blur'},
status:{required:true, message: '请选择', trigger: 'change'},
permission:{required:true, message: '请选择', trigger: 'change'},
});
const formSetting= reactive({
formColumn: [
{component:'el-input',label:'角色名称',key: 'name',attr:{placeholder: '请输入'}},
{component:'el-radio-group',label:'状态',key: 'status',options:[{label:'正常',value: 1},{label:'禁用',value: 0}]},
{component:'el-input',label:'角色说明',key: 'desc',attr:{placeholder: '请输入',maxlength:50}},
{
component: 'slot',
label: '角色权限',
key: 'permission',
},
],
buttonOptions:{
okText:'确定',
cancelText:'取消',
onOk:()=>{
sdata.isLoading = true
},
onCancel: () =>{
sdata.isLoading = false;
}
}
})
return {
sdata,
form,
formRef,
treeRef,
formSetting,
formRules
};
}
})
| 名称 | 说明 | 类型 |
|---|---|---|
| model | 与element plus 原生属性相同,传入表单对象 | object |
| rules | 与element plus 原生属性相同,传入表单校验规则 | object |
| settings | 传入表单配置对象 | object |
const settings = {
formColumn:[], //表单项配置
buttonOptions:{} // 表单提交按钮 重置按钮
}
| 参数 | 类型 | 说明 |
|---|---|---|
| component | string | element puls 表单组件标签名 eg: el-input |
| label | string | 表单项名称 |
| key | string | v-model绑定 |
| hidden | boolean | 切换显示或者隐藏状态,适用于切换类型时候展示不同表单项,默认展示可以不写此参数 |
| attr | object | 属性绑定,理论上支持所有属性 |
| on | object | 事件绑定 目前支持 click change input select 四个事件,后续完善 |
| options | array | options 传入el-select、 el-checkbox-group、el-radio-group选项的数据 |
// input
{
component:'el-input', // 表单项组件名称,支持slot
label:'角色名称', // 表单项名称
key: 'name', // v-model绑定
hidden:false, // 切换显示或者隐藏状态,适用于切换类型时候展示不同表单项,默认展示可以不写此参数
attr:{placeholder: '请输入'},// 属性绑定
on:{ // 事件绑定 目前支持 click change input select 四个事件,后续完善
click:()=>{},
change:()=>{},
input:()=>{},
select:()=>{},
}
},
// select、 checkbox-group、radio-group
{
component:'el-radio-group',
label:'状态',
key: 'status',
options:[{label:'正常',value: 1},{label:'禁用',value: 0}] // options 传入选项数据
},
// slot
{
component: 'slot', // 该项开启slot渲染
label: '角色权限',
key: 'permission',
},
就这么几个属性没啥好说的了,自己看一下就懂了。
buttonOptions:{
okText:'确定',
cancelText:'取消',
onOk:()=>{
},
onCancel: () =>{
}
}
<template>
<el-form :model="model" :inline="inline" :rules="rules" :ref="formRef">
<template v-for="c in settings.formColumn"
:key="c.key">
<el-form-item v-if="!c.hidden"
:prop="c.key"
:label="c.label"
:rules="c.rules"
>
<slot v-if="c.component === 'slot'" :name="c.key"></slot>
<component
v-else
:is="c.component"
v-model="model[c.key]"
:placeholder="c.placeholder"
v-bind="c.attr"
@click="c.on&&c.on.click?c.on.click($event):()=>{}"
@change="c.on&&c.on.change?c.on.change($event):()=>{}"
@input="c.on&&c.on.input?c.on.input($event):()=>{}"
@select="c.on&&c.on.select?c.on.select($event):()=>{}"
>
<template v-if="c.component === 'el-select'">
<el-option v-for="op in c.options" :key="op.value" :value="op.value" :label="op.label"></el-option>
</template>
<template v-if="c.component === 'el-radio-group' && c.options">
<el-radio v-for="op in c.options" :key="op.value" :label="op.value">{{op.label}}</el-radio>
</template>
<template v-if="c.component === 'el-checkbox-group' && c.options">
<el-checkbox v-for="op in c.options" :key="op.value" :label="op.value">{{op.label}}</el-checkbox>
</template>
</component>
</el-form-item>
</template>
<el-form-item>
<div class="width-full text-align-right">
<el-button type="primary"
v-if="settings.buttonOptions && settings.buttonOptions.okText"
@click="onOk">{{settings.buttonOptions.okText}}
</el-button>
<el-button @click="onCancel"
v-if="settings.buttonOptions && settings.buttonOptions.cancelText"
>{{settings.buttonOptions.cancelText}}</el-button>
</div>
</el-form-item>
</el-form>
</template>
import {defineComponent} from 'vue'
const refId = 'formRef-'+ Math.floor(Math.random() * 10000)
export default defineComponent({
name: "EZForm",
props:{
inline:{
type: Boolean,
default: false
},
rules:{
type: Object,
default: ()=>{}
},
model:{
type: Object,
default:()=>{},
required: true
},
settings:{
type: Object,
default: ()=>{},
required: true
}
},
data(){
return{
formRef: refId
}
},
methods: {
onOk() {
this.$refs[refId].validate((v) => {
if (v) {
this.settings.buttonOptions
&& typeof this.settings.buttonOptions.onOk === "function"
&& this.settings.buttonOptions.onOk();
}
})
},
resetFields(){
this.$refs[refId].resetFields()
},
onCancel(){
this.$refs[refId].resetFields()
this.settings.buttonOptions
&& typeof this.settings.buttonOptions.onCancel === "function"
&& this.settings.buttonOptions.onCancel()
}
}
})
封装的好处就是可以减少代码编写,提升代码复用率,提升代码质量。
目前表单并不完善,已知bug:
1.datepicker 组件在开发模式下正常显示,打包后所有日期都看不见了。
2.tree组件不能正常使用,传入数据不能渲染
不过这两都可以通过slot方式进行曲线救国。
以上就是所有内容了,如果有帮到你,请收藏、点赞、评论!