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

这篇具有很好参考价值的文章主要介绍了vue3 ts element plus form表单二次封装详细步骤 (附参数、类型详细介绍及简单使用示例)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

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

效果图

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

预览地址

  • 查看国内预览站

  • 查看国外预览站

1. EasyForm 表单组件封装

src/components/EasyForm/index.vue Form 表单组件封装

<template>
    <el-form @submit.prevent :model="formModel" v-bind="_options" ref="formRef">
        <template v-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-group v-model="formModel[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-group v-model="formModel[item.field]" :disabled="item.disabled">
                    <el-checkbox
                        v-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="formModel[item.field]"
                    clearable
                    :disabled="item.disabled"
                    :label-key="item.options?.labelkey"
                    :value-key="item.options?.valueKey"
                    :select-data="item.options?.data" /> -->
                <el-select v-model="formModel[item.field]" :placeholder="item.options?.placeholder || '请选择'" :clearable="item.clearable">
                    <el-option
                        v-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-input
                    v-model="formModel[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>
            <slot name="buttons" :model="formModel" :formRef="formRef">
                <el-button type="primary" @click="onSubmit(formRef)">{{ _options.submitButtonText }}</el-button>
                <el-button v-if="_options.showResetButton" type="info" @click="resetForm(formRef)">
                    {{ _options.resetButtonText }}
                </el-button>
                <el-button v-if="_options.showCancelButton" @click="emit('cancel')">
                    {{ _options.cancelButtonText }}
                </el-button>
            </slot>
        </el-form-item>
    </el-form>
</template>
<script lang="ts" setup>
    import type { FormInstance } from 'element-plus'
    import { ComputedRef, ref, computed } from 'vue'
    // 父组件传递的值
    interface Props {
        fieldList: Form.FieldItem[]
        model?: Record<Form.FieldItem['field'], Form.FieldItem['value']>
        options?: Form.Options
    }
    // 表单的数据
    const formModel = 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)
    })
    interface EmitEvent {
        (e: 'submit', params: any): void
        (e: 'reset'): void
        (e: 'cancel'): void
    }
    const emit = defineEmits<EmitEvent>()
    defineExpose({
        formRef
    })
    // 根据fieldList初始化model, 如果formModel有传值就用传递的model数据模型,否则就给上面声明的formModel设置相应的(key,value) [item.field], item.value是表单的默认值(选填)
   watch(
	    () => props.model,
	    () => {
	        props.fieldList.map((item: Form.FieldItem) => {
	            // 如果类型为checkbox,默认值需要设置一个空数组
	            const value = item.type === 'checkbox' ? [] : ''
		            props.model ? (formModel.value = props.model) : (formModel.value[item.field] = item.value || value)
		        })
		    },
	    { immediate: true }
		)
    // 提交按钮
    const onSubmit = (formEl: FormInstance | undefined) => {
        if (!formEl) return
        formEl.validate((valid) => {
            if (valid) {
                emit('submit', formModel.value)
            } else {
                return false
            }
        })
    }
    // 输入框回车事件
	const handleKeyUp = (enterable: boolean | undefined) => {
	    if (!enterable) return
	    onSubmit(formRef.value)
	}
	// 重置
    const resetForm = (formEl: FormInstance | undefined) => {
        if (!formEl) return
        formEl.resetFields()
    }
</script>
<style lang="scss" scoped></style>

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

2. 基本表单使用

src/views/form/index.vue

<template>
    <el-card class="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>
<script lang="ts" setup>
    import { exampleForm } from '@/config/form' 
	// import { ref } from 'vue'
	// import EasyForm from '@/components/EasyForm/index.vue'
	// 本项目EasyForm组件自动引入,如复制此代码,需根据路径引入Form组件后使用
    const fieldList: Form.FieldItem[] = exampleForm.base
    const model = ref<Record<string, any>>({
        name: '张三',
        gender: 1,
        hobbies: [1],
        job: 3,
        readonly: '只读输入框',
        summary: '尤雨溪懂个锤子vue是什么梗'
    })
    /**
     * 注意: model数据模型非必填项,如果仅仅是用于数据收集,model参数可以不用填,表单的submit事件会返回所有搜集的数据对象
     *       如果是编辑的情况下,页面需要回显数据,则model数据模型必须要填写
     */
    const handleBaseSubmit = (model: Record<string, any>) => {
        console.log(model)
    }
</script>
<style lang="scss" scoped></style>

3. 自定义 key

src/views/form/index.vue

<template>
    <el-card class="mb-5">
        <template #header> 自定义key </template>
        <easy-form :fieldList="customKeyFieldList" :model="model2" />
    </el-card>
</template>
<script lang="ts" setup>
    import { exampleForm } from '@/config/form'
    // import { ref } from 'vue'
	// import EasyForm from '@/components/EasyForm/index.vue'
	// 本项目EasyForm组件自动引入,如复制此代码,需根据路径引入Form组件后使用
    const customKeyFieldList: 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 }] } },
                ],
     */
    const handleBaseSubmit = (model: Record<string, any>) => {
        console.log(model)
    }
</script>
<style lang="scss" scoped></style>

4. 自定义表单验证

src/views/form/index.vue

<template>
    <el-card class="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>
<script lang="ts" setup>
    import type { FormInstance } from 'element-plus'
    import { exampleForm } from '@/config/form' 
	// import EasyForm from '@/components/EasyForm/index.vue'
	// 本项目EasyForm组件自动引入,如复制此代码,需根据路径引入Form组件后使用
    const ruleFieldList: Form.FieldItem[] = exampleForm.ruleForm
    /**
     *  如果用到了表单验证,又使用slot自定义按钮的话,需要自行实现验证逻辑
     *  组件内部已经集成验证,及重置逻辑。表单验证建议使用内置的提交按钮。当通过验证规则,内置提交按钮才会出发submit事件
     */
    // 下方是使用slot自定义按钮,需要自己实现验证逻辑
    const handleSubmit = (model: any, formEl: FormInstance | undefined) => {
        if (!formEl) return
        formEl.validate((valid) => {
            if (valid) {
                console.log('submit!', model)
            } else {
                console.log('error submit!')
                return false
            }
        })
    }
</script>
<style lang="scss" scoped></style>

src/config/form.ts 表单配置项, 参数请参考下面参数介绍

// 自定义验证邮箱方法
const checkEmail = (rule: any, value: any, callback: any) => {
    if (!value) callback(new Error('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(new Error('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[]

// 表单配置示例
export const 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 参数类型声明(声明为全局的类型,方便使用)

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


参数介绍

Form 属性
参数 说明 类型 是否必填 默认值
model 表单数据对象 Record<string, any>
options 自定义配置 object
fieldList formItem 配置数组 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 false
submitButtonText 提交按钮默认显示的文本内容 string ‘提交’
resetButtonText 重置按钮默认显示的文本内容 string ‘重置’
cancelButtonText 取消按钮默认显示的文本内容 string ‘取消’
showResetButton 是否显示重置按钮 boolean
showCancelButton 是否显示取消按钮 boolean
fieldItem 配置项
参数 说明 类型 是否必填 默认值
field model 的键名 string
label 标签文本 string
type 当前 fieldItem 的类型 ‘password’ / ‘text’ / ‘textarea’ / ‘radio’ / ‘checkbox’ / ‘select’ ‘text’
value 默认显示的值 any
placeholder 输入框占位文本 string
disabled 是否禁用 boolean false
options 如果 type=‘checkbox’ / ‘radio’ / 'select’时,需传入此配置项。格式参考 fieldItem options 配置项 object -
rules 表单验证规则。格式参考element-plus form 表单 或者参数类型声明 Array<RuleItem> -
clearable 是否可清空 boolean false
showPassword 是否显示切换密码图标 boolean false
enterable 当为输入框时,是否启用回车触发提交功能 boolean false
fieldItem options 配置项
参数 说明 类型 是否必填 默认值
labelkey label 自定义字段名 string ‘label’
valueKey value 自定义字段名 string ‘value’
placeholder 当 fieldItem type= 'select’时,选择框的提示语 string -
data type=‘checkbox’ / ‘radio’ / 'select’时, 需要的数据 Array<object> -
Form 插槽
插槽名 说明 插槽作用域
buttons 自定义按钮区域的内容 { model, formRef }
Form 事件
事件名 说明 回调参数
submit 点击默认的提交按钮触发 model
cancel 点击取消按钮触发 -
reset 重置该表单项,将其值重置为初始值,并移除校验结果 -

其他

此文档只提供基本的封装思路,如需使用到更多的业务场景,可自行扩展。
FiledItem type 类型可增加 富文本编辑器、 markdown 编辑器, 上传图片等类型,然后根据类型判断把封装好的富文本编辑器组件、markdown 编辑器组件放入表单内。文章来源地址https://www.toymoban.com/news/detail-470575.html

到了这里,关于vue3 ts element plus form表单二次封装详细步骤 (附参数、类型详细介绍及简单使用示例)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • vue全家桶进阶之路43:Vue3 Element Plus el-form表单组件

    在 Element Plus 中, el-form 是一个表单组件,用于创建表单以便用户填写和提交数据。它提供了许多内置的验证规则和验证方法,使表单验证更加容易。 使用 el-form 组件,您可以将表单控件组织在一起,并对表单进行验证,以确保提交的数据符合预期的格式和要求。该组件具有

    2023年04月20日
    浏览(32)
  • Vue3+Element Plus 关于Dialog弹出Form表单,使用resetFields重置无效的解决

    主要参考了element-plus官方的表单重置按钮(官方Form例子任意reset按钮),然后试了试他的ref绑定,发现可以完美解决重置问题。 第一步:给Form表单绑定ref。绑定ref 的值为refFormInstance();这里注意表单el-form-item必须有prop属性。 2.第二步:在你想要重置的地方调用重置表单方法

    2024年01月21日
    浏览(28)
  • vue3+ts - element-plus封装上传文件图片组件

      近期做到的项目中有涉及到上传图片上传文件的需求,因为是pc管理后台,用到了element-plus框架,所以我也一起使用element-plus中的上传图片上传图片功能,并对它进行封装成一个组件,方便在多个地方使用。 1、上传文件、视频 2、上传图片   在这里上传图片和文件是分

    2024年02月12日
    浏览(34)
  • vue3+ts+elementui-plus二次封装树形表格实现不同层级展开收起的功能

    一、TableTreeLevel组件 

    2024年02月15日
    浏览(45)
  • vue3使用el-form实现登录、注册功能,且进行表单验证(Element Plus中的el-form)

    简介:Element Plus 中的 el-form 是一个表单组件,用于快速构建表单并进行数据校验。它提供了丰富的表单元素和验证规则,使表单开发变得更加简单和高效。可以搭配el-dialog实现当前页面的登录、注册页 ,这两天在vue3中用到了表单登录,特意记录一下,这里没有封装,直接使

    2024年02月07日
    浏览(41)
  • vue3 基于element plus对el-pagination进行二次封装

    在vue3项目中,如果每个列表页都敲一遍分页方法,显然是不合理的,那么,下面我将基于element plus对el-pagination进行二次封装,使用vue3语法糖格式,废话不多说,开干。

    2024年02月12日
    浏览(32)
  • (el-Form)操作(不使用 ts):Element-plus 中 Form 表单组件校验规则等的使用

    1、 Element-plus 提供 Form 表单组件情况: 其一、 Element-plus 自提供的 Form 代码情况为(示例的代码): 代码地址( 直接点击下面 url 跳转 ):https://element-plus.gitee.io/zh-CN/component/form.html#自定义校验规则 其二、页面的显示情况为: 2、目标想修改后的情况: // 此时虽然页面的样式有些变

    2024年02月13日
    浏览(37)
  • 超级详细 最新 vite4+vue3+ts+element-plus+eslint-prettier 项目搭建流程

    系列文章目录 【element-plus】 table表格每行圆角解决方案 element也通用 【Vue3+Vite+Ts+element-plus】使用tsx实现左侧栏菜单无限层级封装 超级详细GitBook和GitLab集成步骤【linux环境】 1.1、项目创建 执行以下代码将vite将会自动生成初始的 vite4+vue3+ts的项目模板,pnpm、npm、yarn 选择一种执

    2024年02月04日
    浏览(47)
  • Vue3中搜索表单的二次封装

    最近使用Vue3+ElementPlus开发项目,从整体上构思组件的封装。能写成组件的内容都进行封装,方便多个地方使用。 受AntDesign的启发,在项目中有搜索表单+table+分页的地方可以封装为一个组件,只需要对组件传入table的列,组成一个配置项,通过配置可以显示搜索表单、table项的

    2024年02月11日
    浏览(29)
  • 基于Vant组件库二次封装组件(TS+Vue3.x环境)

    1. 今天的需求是封装一个 Navigation Bar 导航栏组件,目的是给到App几乎所有的页面复用:      2. 因为之前的项目里使用过Vant组件库,笔者第一时间想到了Vant组件库中的 NavBar 组件,和当前App的需求匹配度很高。Vant组件库的 NavBar 组件: 3. 相信你也发现了,Vant组件库默认主题

    2023年04月18日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包