0


vue3 ts element plus form表单二次封装详细步骤 (附参数、类型详细介绍及简单使用示例)

前言

上篇table 表格封装 讲到项目中经常会用到 table 表格,所以做了封装。当然,form 表单使用的频率依然很高,所以和封装 table 表格的思路相似,对 form 表单也做了一个二次封装的组件。

效果图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

预览地址

  • 查看国内预览站
  • 查看国外预览站

1. EasyForm 表单组件封装

src/components/EasyForm/index.vue

Form 表单组件封装

<template><[email protected]:model="model"v-bind="_options"ref="formRef"><templatev-for="(item, index) in fieldList":key="index"><!-- 单选框 --><el-form-item:label="item.label"v-if="item.type === 'radio'":rules="item.rules":prop="[item.field]"><el-radio-groupv-model="model[item.field]":disabled="item.disabled"><el-radio:label="val[item.options?.valueKey || 'value']"size="large"v-for="val in item.options?.data":key="val[item.options?.valueKey || 'value']">
                        {{ val[item.options?.labelkey || 'label'] }}
                    </el-radio></el-radio-group></el-form-item><!-- 复选框 --><el-form-item:label="item.label"v-else-if="item.type === 'checkbox'":rules="item.rules":prop="[item.field]"><el-checkbox-groupv-model="model[item.field]":disabled="item.disabled"><el-checkboxv-for="c in item.options?.data":key="c[item.options?.valueKey || 'value']":label="c[item.options?.valueKey || 'value']">{{ c[item.options?.labelkey || 'label'] }}</el-checkbox></el-checkbox-group></el-form-item><!-- 下拉框 --><el-form-item:label="item.label"v-else-if="item.type === 'select'":rules="item.rules":prop="[item.field]"><!-- <EasySelect
                    v-model="model[item.field]"
                    clearable
                    :disabled="item.disabled"
                    :label-key="item.options?.labelkey"
                    :value-key="item.options?.valueKey"
                    :select-data="item.options?.data" /> --><el-selectv-model="model[item.field]":placeholder="item.options?.placeholder || '请选择'":clearable="item.clearable"><el-optionv-for="s in item.options?.data":key="s[item.options?.valueKey || 'value']":label="s[item.options?.labelkey || 'label']":value="s[item.options?.valueKey || 'value']"/></el-select></el-form-item><!-- 默认输入框 --><el-form-item:label="item.label":rules="item.rules":prop="[item.field]"v-else><el-inputv-model="model[item.field]":readonly="item.readonly":type="item.type ?? 'text'":placeholder="item.placeholder || item.label":disabled="item.disabled":showPassword="item.showPassword":clearable="item.clearable"@keyup.enter="handleKeyUp(item.enterable)"/></el-form-item></template><el-form-item><slotname="buttons":model="model":formRef="formRef"><el-buttontype="primary"@click="onSubmit(formRef)">{{ _options.submitButtonText }}</el-button><el-buttonv-if="_options.showResetButton"type="info"@click="resetForm(formRef)">
                    {{ _options.resetButtonText }}
                </el-button><el-buttonv-if="_options.showCancelButton"@click="emit('cancel')">
                    {{ _options.cancelButtonText }}
                </el-button></slot></el-form-item></el-form></template><scriptlang="ts"setup>import type { FormInstance }from'element-plus'import{ ComputedRef, ref, computed }from'vue'// 父组件传递的值interfaceProps{fieldList: Form.FieldItem[]
        model?: Record<string, any>
        options?: Form.Options
    }// 表单的数据const model = ref<Record<string, any>>({})const formRef = ref<FormInstance>()const props = defineProps<Props>()// 设置option默认值,如果传入自定义的配置则合并option配置项const_options: ComputedRef<Form.Options>=computed(()=>{const option ={labelPosition:'right',disabled:false,submitButtonText:'提交',resetButtonText:'重置',cancelButtonText:'取消'}return Object.assign(option, props?.options)})interfaceEmitEvent{(e:'submit',params: any):void(e:'reset'):void(e:'cancel'):void}const emit = defineEmits<EmitEvent>()defineExpose({
        formRef
    })// const model = ref<Record<string, any>>({})// 根据fieldList初始化model, 如果model有传值就用传递的model数据模型,否则就给上面声明的model设置相应的(key,value) [item.field], item.value是表单的默认值(选填)
    props.fieldList.map((item: Form.FieldItem)=>{// 如果类型为checkbox,默认值需要设置一个空数组const value = item.type ==='checkbox'?[]:''
        props.model ?(model.value = props.model):(model.value[item.field]= item.value || value)})// 提交按钮constonSubmit=(formEl: FormInstance |undefined)=>{if(!formEl)return
        formEl.validate((valid)=>{if(valid){emit('submit', model.value)}else{returnfalse}})}// 输入框回车事件consthandleKeyUp=(enterable: boolean |undefined)=>{if(!enterable)returnonSubmit(formRef.value)}// 重置constresetForm=(formEl: FormInstance |undefined)=>{if(!formEl)return
        formEl.resetFields()}</script><stylelang="scss"scoped></style>

复制完Form组件的代码后,会报红线,Form.XXXXX 找不到,这个是全局类型声明。 声明文件已在下方贴出来,直接复制进项目中, 红色警告自然消失。

2. 基本表单使用

src/views/form/index.vue
<template><el-cardclass="mb-5"><template#header> 基本表单 </template><easy-form:fieldList="fieldList":model="model"@submit="handleBaseSubmit"><!-- 如果不使用默认的按钮可以使用插槽自定义内容, 插槽返回的model就是当前表单的数据 --><!-- <template #buttons="{ model }">
                    <el-button">提交</el-button>
                </template> --></easy-form></el-card></template><scriptlang="ts"setup>import{ exampleForm }from'@/config/form'// import { ref } from 'vue'// import EasyForm from '@/components/EasyForm/index.vue'// 本项目EasyForm组件自动引入,如复制此代码,需根据路径引入Form组件后使用constfieldList: Form.FieldItem[]= exampleForm.base
    const model = ref<Record<string, any>>({name:'张三',gender:1,hobbies:[1],job:3,readonly:'只读输入框',summary:'尤雨溪懂个锤子vue是什么梗'})/**
     * 注意: model数据模型非必填项,如果仅仅是用于数据收集,model参数可以不用填,表单的submit事件会返回所有搜集的数据对象
     *       如果是编辑的情况下,页面需要回显数据,则model数据模型必须要填写
     */consthandleBaseSubmit=(model: Record<string, any>)=>{
        console.log(model)}</script><stylelang="scss"scoped></style>

3. 自定义 key

src/views/form/index.vue
<template><el-cardclass="mb-5"><template#header> 自定义key </template><easy-form:fieldList="customKeyFieldList":model="model2"/></el-card></template><scriptlang="ts"setup>import{ exampleForm }from'@/config/form'// import { ref } from 'vue'// import EasyForm from '@/components/EasyForm/index.vue'// 本项目EasyForm组件自动引入,如复制此代码,需根据路径引入Form组件后使用constcustomKeyFieldList: Form.FieldItem[]= exampleForm.customkeyForm
    const model2 = ref<Record<string, any>>({name:'自定义key',gender:1})/**
     * 注意: 如果使用到checkbox,radio,或者select等组件,需要传入组件额外需要的数据,本组件默认设定的读取数据的字段是 label, value
     *       可参考下方声明文件 FiledItem options的参数类型描述
     *       比如,当前传入的data数据字段名和label、value不匹配,可使用预留的参数 labelkey, valueKey指定字段名
     *         customkeyForm: [
                    { label: '标题', field: 'name' },
                    { label: '性别', field: 'gender', type: 'radio', options: { labelkey: 'title', valueKey: 'val', data: [{ title: '男', val: 1 }, { title: '女', val: 0 }] } },
                ],
     */consthandleBaseSubmit=(model: Record<string, any>)=>{
        console.log(model)}</script><stylelang="scss"scoped></style>

4. 自定义表单验证

src/views/form/index.vue
<template><el-cardclass="mb-5"><template#header> 自定义验证的表单 (使用slot自定义按钮) </template><easy-form:fieldList="ruleFieldList"><!-- 如果不使用默认的按钮可以使用插槽自定义内容, 插槽返回的model就是当前表单的数据, formRef是当前表单的FormInstance --><template#buttons="{ model, formRef }"><el-button@click="handleSubmit(model, formRef)">保存</el-button></template></easy-form></el-card></template><scriptlang="ts"setup>import type { FormInstance }from'element-plus'import{ exampleForm }from'@/config/form'// import EasyForm from '@/components/EasyForm/index.vue'// 本项目EasyForm组件自动引入,如复制此代码,需根据路径引入Form组件后使用construleFieldList: Form.FieldItem[]= exampleForm.ruleForm
    /**
     *  如果用到了表单验证,又使用slot自定义按钮的话,需要自行实现验证逻辑
     *  组件内部已经集成验证,及重置逻辑。表单验证建议使用内置的提交按钮。当通过验证规则,内置提交按钮才会出发submit事件
     */// 下方是使用slot自定义按钮,需要自己实现验证逻辑consthandleSubmit=(model: any,formEl: FormInstance |undefined)=>{if(!formEl)return
        formEl.validate((valid)=>{if(valid){
                console.log('submit!', model)}else{
                console.log('error submit!')returnfalse}})}</script><stylelang="scss"scoped></style>
src/config/form.ts

表单配置项, 参数请参考下面参数介绍

// 自定义验证邮箱方法constcheckEmail=(rule: any,value: any,callback: any)=>{if(!value)callback(newError('Please input the email'))const regExp =/^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.(com|cn|net)$/
    regExp.test(value)?callback():callback(newError('Please input the correct email address'))}// // 自定义验证表单配置数据// export const validationFormFieldList = [//     { label: '姓名', field: 'name', rules: [{ required: true, message: 'name is required' }] },//     { label: '邮箱', field: 'email', rules: [{ required: true, validator: checkEmail }] },// ] as Form.FieldItem[]// 表单配置示例exportconst exampleForm ={base:[{label:'姓名',field:'name',disabled:true},{label:'性别',field:'gender',type:'radio',options:{data:[{label:'男',value:1},{label:'女',value:0}]}},{label:'爱好',field:'hobbies',type:'checkbox',options:{data:[{label:'吃饭',value:1},{label:'睡觉',value:2},{label:'写代码',value:3}]}},{label:'工作',field:'job',type:'select',options:{data:[{label:'吃饭',value:1},{label:'睡觉',value:2},{label:'写代码',value:3}]}},{label:'密码',field:'password',type:'password',placeholder:'这是一个密码输入框'},{label:'只读',field:'readonly',readonly:true,placeholder:'这是一个只读输入框'},{label:'留言板',field:'summary',type:'textarea',placeholder:'留言板'},],customkeyForm:[{label:'标题',field:'name'},{label:'性别',field:'gender',type:'radio',options:{labelkey:'title',valueKey:'val',data:[{title:'男',val:1},{title:'女',val:0}]}},],ruleForm:[{label:'姓名',field:'name',rules:[{required:true,message:'name is required'}]},{label:'邮箱',field:'email',rules:[{required:true,validator: checkEmail }]},]}as Record<string, Form.FieldItem[]>
src/types/form/index.d.ts

参数类型声明(声明为全局的类型,方便使用)

declare namespace Form {
     type ItemType ='password'|'text'|'textarea'|'radio'|'checkbox'|'select'// 当FiledItem的type === 'radio' | 'checkbox'时,options的参数类型interfaceIFieldOptions{
        labelkey?: string,
        valueKey?: string,
        placeholder?: string,data: Recode<string, any>[]}interfaceOptions{
        labelWidth?: string | number,
        labelPosition?:'left'|'right'|'top',
        disabled?: boolean,
        size?:'large'|'small'|'default',
        showResetButton?: boolean,// 是否展示重置按钮
        showCancelButton?: boolean,// 是否展示取消按钮
        submitButtonText?: string,
        resetButtonText?: string,
        cancelButtonText?: string
    }interfaceFieldItem{
        label?: string,
        labelWidth?: string | number,// 标签宽度,例如 '50px'。 可以使用 auto。field: string,
        type?: ItemType,
        value?: any,
        placeholder?: string,
        disabled?: boolean,
        readonly?: boolean,
        options?: IFieldOptions,
        rules?:import('element-plus').FormItemRule[]
        clearable?: boolean // 是否可清空
        showPassword?: boolean,// 是否显示切换密码图标
        enterable?: boolean,// 当为输入框时,是否启用回车触发提交功能}}

参数介绍

Form 属性

参数说明类型是否必填默认值model表单数据对象Record<string, any>否—options自定义配置object否—fieldListformItem 配置数组Array<object>是—

Options 配置项

参数说明类型是否必填默认值labelWidth标签的长度,例如 ‘50px’。 作为 Form 直接子元素的 form-item 会继承该值。 可以使用 auto。string / number否—labelPosition表单域标签的位置, 当设置为 left 或 right 时,则也需要设置 label-width 属性‘left’ / ‘right’ / ‘top’否‘right’size用于控制该表单内组件的尺寸large / default /small否—disabled是否禁用该表单内的所有组件。 如果设置为 true, 它将覆盖内部组件的 disabled 属性。boolean否falsesubmitButtonText提交按钮默认显示的文本内容string否‘提交’resetButtonText重置按钮默认显示的文本内容string否‘重置’cancelButtonText取消按钮默认显示的文本内容string否‘取消’showResetButton是否显示重置按钮boolean否—showCancelButton是否显示取消按钮boolean否—

fieldItem 配置项

参数说明类型是否必填默认值fieldmodel 的键名string是—label标签文本string是—type当前 fieldItem 的类型‘password’ / ‘text’ / ‘textarea’ / ‘radio’ / ‘checkbox’ / ‘select’否‘text’value默认显示的值any否—placeholder输入框占位文本string否—disabled是否禁用boolean否falseoptions如果 type=‘checkbox’ / ‘radio’ / 'select’时,需传入此配置项。格式参考 fieldItem options 配置项object否-rules表单验证规则。格式参考element-plus form 表单 或者参数类型声明Array<RuleItem>否-clearable是否可清空boolean否falseshowPassword是否显示切换密码图标boolean否falseenterable当为输入框时,是否启用回车触发提交功能boolean否false

fieldItem options 配置项

参数说明类型是否必填默认值labelkeylabel 自定义字段名string否‘label’valueKeyvalue 自定义字段名string否‘value’placeholder当 fieldItem type= 'select’时,选择框的提示语string否-datatype=‘checkbox’ / ‘radio’ / 'select’时, 需要的数据Array<object>否-

Form 插槽

插槽名说明插槽作用域buttons自定义按钮区域的内容{ model, formRef }

Form 事件

事件名说明回调参数submit点击默认的提交按钮触发modelcancel点击取消按钮触发-reset重置该表单项,将其值重置为初始值,并移除校验结果-

其他

此文档只提供基本的封装思路,如需使用到更多的业务场景,可自行扩展。
FiledItem type 类型可增加 富文本编辑器、 markdown 编辑器, 上传图片等类型,然后根据类型判断把封装好的富文本编辑器组件、markdown 编辑器组件放入表单内。


本文转载自: https://blog.csdn.net/weixin_45291937/article/details/126275955
版权归原作者 zhfy啊 所有, 如有侵权,请联系我们删除。

“vue3 ts element plus form表单二次封装详细步骤 (附参数、类型详细介绍及简单使用示例)”的评论:

还没有评论