Vue3 +ElementPlus 实现表单组件的封装,通过JSON控制表单数据

Vue3 +ElementPlus 实现表单组件的封装,通过JSON控制表单数据

在日常开发后台管理系统时,经常会遇见各种各样的表单,如果没有一个公共的表单组件,在开发过程中就会出现表单样式的不统一及复杂的代码,不利于代码的维护,故此封装一个公共的表单组件极为重要。

  • 主要分为两个文件 PublicFormComponents.vueform.d.ts

PublicFormComponents.vue

<template>
    <div>
        <el-row :gutter='gutter'>
            <el-col
                v-for='(item,index) in formArray'
                :key='index'
                :xs="item.row.xs"
                :sm="item.row.sm"
                :md="item.row.md"
                :lg="item.row.lg"
                :xl="item.row.xl">
                <!-- 普通的文字显示 -->
                <el-form-item :label="item.label" :prop='item.prop' v-if="item.type == 'span'">
                    <span style='margin-left: 20px;color: #606266;text-align: start'>{{formObject[item.value]}}</span>
                </el-form-item>

                <el-tooltip
                    class="box-item"
                    effect="dark"
                    :content="item.tooltipText"
                    placement="bottom"
                    :disabled='!item.tooltipDisabled'
                    v-else
                >
                    <el-form-item :label="item.label" :prop='item.prop' >
                        <!-- 选择器 -->
                        <el-select
                            v-if="item.type == 'select'"
                            v-model="formObject[item.value]"
                            :placeholder="item.placeholder"
                            :disabled='item.disabled'
                            :multiple='item.multiple'
                            :value-key="'label'"
                            :clearable='!item.clearable'
                            :size="item.size ||'default'"
                            @change="selectChange($event,item.value)"
                        >
                            <el-option
                                v-for="(items,indexs) in item.options"
                                :key="indexs"
                                :label="items.label"
                                :value="items.value"
                            />
                        </el-select>
                        <!-- 级联选择器 -->
                        <el-cascader
                            v-if="item.type == 'cascader'"
                            ref="elCascader"
                            v-model="formObject[item.value]"
                            :options="item.options"
                            :placeholder="item.placeholder"
                            :clearable='!item.clearable'
                            :disabled='item.disabled'
                            :props='item.props'
                            :show-all-levels="item.showAllLevels"
                            :size="item.size ||'default'"
                            @change='cascaderChange($event,item.value)'
                        />
                        <!-- 输入框 -->
                        <el-input
                            v-if="item.type == 'input' || item.type == 'textarea' || item.type == 'number' "
                            v-model="formObject[item.value]"
                            :disabled='item.disabled'
                            :placeholder="item.placeholder"
                            :type='item.type'
                            :maxlength="item.maxlengthShow ? item.maxlength : ''"
                            autosize
                            :size="item.size ||'default'"
                            :clearable='!item.clearable'
                            @blur='inputBlur($event,item.value)'
                            @focus='inputFocus($event,item.value)'
                            @change='inputChange($event,item.value)'
                        />
                        <!-- 时间日期选择器 -->
                        <el-date-picker
                            v-if="item.type == 'date' || item.type == 'monthrange' || item.type == 'datetimerange' || item.type == 'datetime' || item.type == 'daterange'"
                            v-model="formObject[item.value]"
                            style='width: 100%'
                            :disabled='item.disabled'
                            :value-format="item.format"
                            :format="item.format"
                            :type="item.type"
                            :placeholder="item.placeholder"
                            :start-placeholder='item.startPlaceholder'
                            :end-placeholder='item.endPlaceholder'
                            :size="item.size ||'default'"
                            :clearable='!item.clearable'
                            @change='dataPickerChange($event,item.value)'
                            :range-separator='item.rangeSeparator'
                            :editable='false'
                            :shortcuts="item.shortcuts"
                        />
                    </el-form-item>
                </el-tooltip>
            </el-col>
            <slot name="custom">
                <!-- 自定义表单项插槽-->
            </slot>
            <slot name="button">
				<!-- 按钮插槽 -->
            </slot>
        </el-row>
    </div>
</template>

<script lang='ts' setup>
import { reactive, ref, toRefs } from 'vue';

const props = defineProps({
    //表单数组
    formArray:{
        type: Array,
        default: () => {
            return [];
        }
    },
    //表单对象
    formObject:{
        type: Object,
        default: () => {
            return {};
        }
    },
    gutter:{
        type: Number,
        default: 24
    }
})

const { formArray , formObject } = toRefs(props);



const emit = defineEmits(
    ['selectChange','cascaderChange','inputBlur','inputFocus','inputChange','dataPickerChange']
);
//以下为表单的部分输入框的监听事件
const selectChange = (e:any,value:string) => {
    emit('selectChange',{data:e,value:value});
}
const cascaderChange = (e:any,value:string) => {
    emit('cascaderChange',{data:e,value:value});
}
const inputBlur = (e:any,value:string) => {
    emit('inputBlur',{data:e,value:value});
}
const inputFocus = (e:any,value:string) => {
    emit('inputFocus',{data:e,value:value});
}
const inputChange = (e:any,value:string) => {
    emit('inputChange',{data:e,value:value});
}
const dataPickerChange = (e:any,value:string) => {
    emit('dataPickerChange',{data:e,value:value});
}
</script>

<style scoped lang='scss'>
:deep(.el-form-item){
    align-items: center !important;
    width: 100%;
}
:deep(.el-select){
    width: 100%;
}
:deep(.el-input__wrapper){
    width: 100%;
}
:deep(.el-cascader){
    width: 100%;
}
:deep(.is-disabled .el-input__inner){
    cursor: pointer !important;
}
:deep(.is-disabled .el-textarea__inner){
    cursor: pointer !important;
}
</style>

  • form.d.ts
type rowType = {
    xs:number,
    sm:number,
    md:number,
    lg:number,
    xl:number,
}
export type formType =  Array<{
    label?:string,//表单的label
    value?:string,//v-model绑定的字段
    prop?:string,//必填校验
    options?:any,//type为select/cascader时的下拉数据
    type?:string,//输入框类型,类型:input、select、cascader、number、date、textarea、datetimerange、datetime
    placeholder?:string,//输入框的提示语
    startPlaceholder?:string,//输入框的开始提示语
    endPlaceholder?:string,//输入框的结束提示语
    rangeSeparator?:string,//时间范围选择器的中间提示语
    size?:string,//输入框的大小,可选值为large、small、default或者不设置
    props?:any,//当type为cascader时设置的数据格式
    row:rowType,//栅格布局
    multiple?:boolean,//是否多选
    maxlengthShow?:boolean,//是否设置字数上限,默认为false
    maxlength?:string,//字数上限
    disabled?:boolean,//是否禁用,默认为false
    format?:string,//当type为date时的时间格式
    showAllLevels?:boolean,
    shortcuts?:Array<{ text: string, value: Date | Function }>,//当type为date时的时间格式
    clearable?:boolean,//是否显示清除按钮
    tooltipDisabled?:boolean,//是否显示tooltip,默认禁用
    tooltipText?:string,//tooltip提示的文字,当tooltipDisabled为false时生效
}>

组件的使用方法

<PublicFormComponents :form-array='parmasArray' :form-object='queryParams'></PublicFormComponents >

import { formType } from '@/types/form';
import { reactive } from 'vue';

const from : formType = reactive([
	{ label: '213', value:'12' , prop: '123',options:[] , type: 'cascader', placeholder:'123', props:{value:'id', label:'name', children:'children', checkStrictly: true,},row:{xs:24,sm:24,md:24,lg:24,xl:24} },
])
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值