ElementUI-Form表单二次封装

news2024/11/26 22:45:12

一、Form组件二次封装考虑组件构成:

  1. form组件:
  2. input text passworld
  3. select
  4. checkbox
  5. radio
  6. 文本域
  7. 日期

二、实现Form表单的二次封装:

1. 分析出对应的位置 开始抽离组件

2. 如果需要产生多个form表单,则需要产生多个el-form-item,则需要一个数据来循环渲染form-item

3. 结合form表单属性继续分析:

    - el-form-item:label 显示文本

    - 内部标签:el-input v-model绑定数据 placeholder 文本提示等等

4. 首先确认一个集合,配置内部属性:比如name,placeholder,type,size,width等等

🔰其中name使用配置使用哪一种表单(input,elbutton)

 5. 在结合form表单v-model定义一个表单数据对象formData。

 

 6. 修改二次封装组件代码中循环formConfig配置产生form

     - 首先先要导入需要使用的element-ui组件

// 按需引入组件
import { ElInput, ElRadioGroup, ElRadioButton, ElDatePicker } from 'element-plus'

    - 配置formConfig表单配置集合,form-item循环该配置自动生成多个form-item,该formConfig是从父组件通过props传过来的值,所以需要使用defineProps来进行接收

interface propTypes {
    formData: any;
    formConfig: Array<{
        name: string;
        placeholder?: string;
        label?: string;
        key: string;
        type?: string;
        size?: string;
        width?: string
        children?: Array<{
            label: string
            value: string
        }>
    }>
}
const props = defineProps<propTypes>()

注意:因为form-item需要循环formConfig,所以formConfig为数组类型。

 扩展:这里需要注意的是如果需要给defineProps设置默认值(el-table组件的二次封装需要设置默认值)时,使用withDefaults()

interface PropType {
   tableData?: Array<any>
   columnKey?: Array<any>,
   title: Array<any>,
   border?: Boolean,
   // 分页参数:
   pageSizes?: Array<any>,
   layout?: string,
   total?: number
}
const props = withDefaults(defineProps<PropType>(),{layout:'total, prev, pager, next,sizes',total:18,pageSizes:()=>[5,10,15,20]})

        - 在template组件中循环生成form-item

<template>
  <el-form :inline="true" class="demo-form-inline">
    <!-- 循环遍历产生Form组件 -->
    <template v-for="(item, index) in formConfig">
      <el-form-item :label="item.label">
        <el-input :placeholder="item.placeholder" />
      </el-form-item>
    </template>
  </el-form>
</template>

7. 分析简易封装之后的代码,得知el-input不是固定的,需要根据配置中的key动态切换,可以使用vue中component组件的动态挂载来完成

相当于因为循环的是formConfig,而formConfig中的key值是需要绑定的key值,也就是后端需要请求的字段,然后formData对象中存储的刚好是后端需要的字段所以根据对象的中括号来获取key值

 <!-- 使用组件的动态挂载 -->
<component :is="UICcom[item.name]" :placeholder="item.placeholder" v- model="formData[item.key]"@click="RadioGroup">
 <template v-if="item.children && item.children.length">
  <el-radio-button v-for="its in item.children" :label="its.value">{{ its.label}}
  </el-radio-button>
 </template>
</component>

        -  定义对象存储UI组件

interface UIComType{
    [propName:string]:any
}

let UICom:UIComType = {
    ElInput:ElInput
}

🔰这里需要使用TS对UICom做类型限制否则在动态挂载组件时会报错。这里对属性值不明确的情况下使用[propName:string]:any

8. 父组件使用

        - 在父组件中配置form表单配置:

const formConfig = [
    {
        name: 'ElRadioGroup',
        label: '时间选择:',
        key: 'data',
        type: 'DatePick',
        width: '6',
        children: [
            {
                value: '',
                label: '全部'
            }

        ],

    }
]

        - 在组件中配置form表单数据源:formData: 绑定form表单中的数据,form表单根据key值来配置v-model的值,这里form表单中的元素都是后端需要请求的字段

const FormData = ref({
    paid: '',
    extract_type: '',
    nickname: '',
    data: '',
    page: 1,
    limit: 5
})

        - 导入form表单组件并动态绑定formConfig、formData

<FormVue :form-config="formConfig" 
 :form-data="FormData" 
 @FormEvent="FormEvent">
</FormVue>

效果图:

 9. 若像是el-select、el-radio-group需要子项,则需要在formConfig中添加children数组,封装组件这里需要对这种包含子项的组件使用component组件动态加载并使用判断。

{
        name: 'ElRadioGroup',
        label: '时间选择:',
        key: 'data',
        type: 'DatePick',
        width: '6',
        children: [
            {
                value: '',
                label: '全部'
            },
            {
                value: 'today',
                label: '今天'
            },

        ],

    },
<el-form-item :label="item.label" v-for="(item, index) in formConfig" :key="index">
                    <!-- 使用组件的动态挂载 -->
                   <component :is="UICcom[item.name]"  :placeholder="item.placeholder" v-model="formData[item.key]">
                        <template v-if="item.children && item.children.length > 0">
                            <el-radio-button v-for="its in item.children" :label="its.value">{{ its.label
                            }}</el-radio-button>
                        </template>
                        <template v-else>
                            <!-- 使用组件的动态挂载 -->
                            <component :is="UICcom[item.name]" :placeholder="item.placeholder" v-model="formData[item.key]"
                                @click="RadioGroup">
                                <template v-if="item.children && item.children.length">
                                    <el-radio-button v-for="its in item.children" :label="its.value">{{ its.label
                                    }}</el-radio-button>
                                </template>
                            </component>
                        </template>
                    </component>
                </el-form-item>

效果图:

 但是我们发现所有的表单都在一行,所以就需要添加el-row和el-col

 代码:

 在这里需要注意的是如果需要在一行中添加两个表单组件,则需要将formConfig结构改为数组类型。

 然后在父组件中的formConfig中进行改变,将每一项全部改为数组类型,并且如果哪一行需要几个表单则在该数组中添加n个对象。

 form二次封装表单使用$emit来向父组件传递值:

const emit = defineEmits<{ (e: 'FormEvent', val: any): void }>()
const RadioGroup = () => {
    console.log(props.formData);
    emit('FormEvent', props.formData)
}

🔰将绑定的formData传递给父组件

form表单二次封装的整体代码:

<template>
    <el-form label-position="left" :model="formData" :inline="true" >
        <!-- <template > -->
        <el-row v-for="(items, index) in formConfig" :key="index">
            <el-col v-for="(item, index) in items" :span="10" :key="index">
                <el-form-item :label="item.label">
                    <!-- 使用组件的动态挂载 -->
                    <component :is="UICcom[item.name]" :placeholder="item.placeholder" v-model="formData[item.key]">
                        <template v-if="item.children && item.children.length > 0">
                            <el-radio-button v-for="its in item.children" :label="its.value">{{ its.label
                            }}</el-radio-button>
                        </template>
                        <template v-else>
                            <!-- 使用组件的动态挂载 -->
                            <component :is="UICcom[item.name]" :placeholder="item.placeholder" v-model="formData[item.key]"
                                @click="RadioGroup">
                                <template v-if="item.children && item.children.length">
                                    <el-radio-button v-for="its in item.children" :label="its.value">{{ its.label
                                    }}</el-radio-button>
                                </template>
                            </component>
                        </template>
                    </component>
                </el-form-item>
            </el-col>
        </el-row>

    </el-form>
</template>

<script lang="ts" setup>
// import {reactive} from 'vue'
// 按需引入组件
import { ElInput, ElRadioGroup, ElRadioButton, ElDatePicker } from 'element-plus'
interface propTypes {
    formData: any;
    formConfig: Array<Array<{
        name: string;
        placeholder?: string;
        label?: string;
        key: string;
        type?: string;
        size?: string;
        width?: string
        children?: Array<{
            label: string
            value: string
        }>
    }>>
}
const props = defineProps<propTypes>()
// 定义对象存储key:UI组件
interface UIComType {
    [propName: string]: any
}
let UICcom: UIComType = {
    "ElInput": ElInput,
    "ElRadioGroup": ElRadioGroup,
    "ElDatePicker": ElDatePicker
}
const RadioGroup = () => {
    console.log(props.formData);
    emit('FormEvent', props.formData)
}
const emit = defineEmits<{ (e: 'FormEvent', val: any): void }>()

</script>

<style lang="scss" scoped></style>

父组件使用代码:

 <FormVue  :form-config="formConfig" :form-data="FormData" @FormEvent="FormEvent"></FormVue>
const formConfig = [
    [{
        name: 'ElRadioGroup',
        label: '时间选择:',
        key: 'data',
        type: 'DatePick',
        width: '6',
        children: [
            {
                value: '',
                label: '全部'
            },
            {
                value: 'today',
                label: '今天'
            },
            {
                value: 'yesterday',
                label: '昨天'
            },
            {
                value: 'week',
                label: '本周'
            },
            {
                value: 'month',
                label: '本月'
            },
            {
                value: 'quarter',
                label: '本季度'
            },
            {
                value: 'year',
                label: '本年'
            },

        ],

    },
    {
        name: 'ElInput',
        label: '搜索:',
        placeholder: '请输入用户昵称,订单号',
        key: 'nickname'
    }
    ],

    [{
        name: 'ElRadioGroup',
        label: '支付类型:',
        key: 'paid',
        type: 'DatePick',
        width: '6',
        children: [
            {
                value: '',
                label: '全部'
            },
            {
                value: '1',
                label: '已支付'
            },
            {
                value: '0',
                label: '未支付'
            },
        ],

    }],
    [{
        name: 'ElInput',
        label: '搜索:',
        placeholder: '请输入用户昵称,订单号',
        key: 'nickname'
    }]
]
const FormData = ref({
    paid: '',
    extract_type: '',
    nickname: '',
    data: '',
    page: 1,
    limit: 5
})

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/598465.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

学习路之gis--百度离线地图下载制作

在有些情况下需要使用地图&#xff0c;但又不能访问外网&#xff0c;这时你需要一个离线地图。本文介绍如何制作百度离线地图。 下面将介绍如何实现一个离线版百度地图&#xff1a; 1. 下载百度地图瓦片 下载网址&#xff1a;望远网-百度地图下载 首先需选择下载地图瓦片的样式…

BUG: scheduling while atomic: fpv_cams/605/0x00010001

IIO框架下IMU驱动的接口在定时器中断内调用报错&#xff0c;因调用IO读定时间较长会导致睡眠的发生&#xff0c;因为内核总是崩。 尝试了几种解决方法&#xff1a; 1.在IIO框架里&#xff0c;使用 spidev 的接口来读写&#xff0c;错误依旧&#xff1b; 2.去掉IIO框架&#x…

香橙派One(全志H3芯片)编译烧写U-boot、Linux内核zImage、dtb

一、编译烧写u-boot 1.1 源码和工具下载&#xff1a; 香橙派提供了u-boot源码和交叉编译链工具&#xff1a; &#xff08;1&#xff09;u-boot&#xff08;2020.04&#xff09;下载地址&#xff1a;https://github.com/orangepi-xunlong/u-boot-orangepi &#xff08;2&#…

MyBatis - MyBatis Generator

文章目录 1.什么是 MyBatis Generator2.使用 MyBatis Generator2.1 导入依赖2.2 application 配置2.3 添加 Java 配置2.4 MBG 配置2.5 生成代码2.6 基本 CRUD 操作 3.进阶使用 MyBatis Generator3.1 基于条件的 CRUD3.2 子查询、Group 与 Join 查询3.3 一对一查询、一对多查询 …

ANSYS Workbench中的网格优化方法

自 50 年代后期以来&#xff0c;有限元法 (FEM) 已被用作解决工程问题的强大工具。当时的计算是手工进行的&#xff0c;该方法是基于力的&#xff0c;而不是我们今天使用的基于位移的方法。由于计算机工业的进步&#xff0c;已经开发出各种有限元商业软件。Ansys 可以被认为是全…

Nginx网站部署

Nginx网站部署 一、访问状态统计配置二、基于授权的访问控制三、基于客户端的访问控制四、基于域名的 Nginx 虚拟主机五、基于IP 的 Nginx 虚拟主机六、基于端口的 Nginx 虚拟主机 一、访问状态统计配置 1.先使用命令/usr/local/nginx/sbin/nginx -V 查看已安装的 Nginx 是否包…

常用抓包工具使用-wireshark使用(二)

常用抓包工具使用-wireshark使用&#xff08;二&#xff09; 文章目录 常用抓包工具使用-wireshark使用&#xff08;二&#xff09;前言一、wireshark安装1.1 windows安装1.2 mac安装 二、wireshark抓包和过滤2.1 打开Wireshark2.2 选择网络接口&#xff1a;2.3 wireshark抓包页…

【Nginx 网络服务】

目录 一、Nginx和Apache的优点和缺点二、编译安装Nginx服务1.关闭防火墙&#xff0c;将安装nginx所需软件包传到/opt目录下2.安装依赖包3.创建运行用户、组4.编译安装Nginx5.检查、启动、重启、停止 nqinx服务 三、认识Nginx服务的主配置文件 nginx.conf1、系统文件支持数量2&a…

商场内怎么导航?商场导航图怎么画?

商场内怎么导航&#xff1f;大型购物商场是目前一二线城市最常见的购物场所&#xff0c;占地面积较大&#xff0c;布局错综复杂&#xff0c;商品比较齐全&#xff0c;如果没有商场地图导航&#xff0c;会导致新顾客难以找到想要的商品&#xff0c;那么大型购物商场商场地图怎么…

索引特性.

目录 没有索引&#xff0c;可能会有什么问题认识磁盘MySQL与存储先来研究一下磁盘在看看磁盘中一个盘片扇区定位扇区结论磁盘随机访问(Random Access)与连续访问(Sequential Access) MySQL 与磁盘交互基本单位建立共识索引的理解建立测试表插入多条记录查看插入结果中断一下---…

打跑个人开源转角的“拦路虎”——我的开源之路

从参与Apache 开源项目&#xff0c;到凭借业务需求独自开发个人开源项目&#xff1b;从项目开源出来无人问津到至今500star&#xff0c;多个企业级用户&#xff0c;在开源过程中&#xff0c;我也从走过低谷&#xff0c;一度想过放弃&#xff0c;但仍然选择坚持至今日。 这一路…

Data Distillation: A Survey

本文是蒸馏学习综述系列的第二篇文章&#xff0c;Data Distillation: A Survey的一个翻译 数据蒸馏&#xff1a;综述 摘要1 引言2 数据蒸馏框架2.1 元模型匹配的数据蒸馏2.2 梯度匹配的数据蒸馏2.3 轨迹匹配的数据蒸馏2.4 分布匹配的数据蒸馏2.5 因式分解的数据蒸馏 3 数据模态…

深度探索:Qt CMake工程编译后的自动打包策略

深度探索&#xff1a;Qt CMake工程编译后的自动打包策略 1. 引言&#xff08;Introduction&#xff09;1.1 Qt和CMake的基本概念&#xff08;Basic Concepts of Qt and CMake&#xff09;1.2 自动打包的重要性&#xff08;Importance of Automatic Packaging&#xff09; 2. Qt…

ELK +Filebeat日志分析系统

一、 ELK日志分析系统概述 1、ELK简介 ELK是三个开源软件的缩写&#xff0c;分别表示&#xff1a;Elasticsearch , Logstash, Kibana , 它们都是开源软件。新增了一个FileBeat&#xff0c;它是一个轻量级的日志收集处理工具(Agent)&#xff0c;Filebeat占用资源少&#xff0c…

我是如何将家里的台式机改成服务器的

大家好,我是雄雄,欢迎关注微信公众号:雄雄的小课堂 文章目录 前言准备工作电脑宽带公网ip光猫给成桥接方式设置路由器设置服务器静态ip地址前言 搞研发的伙伴们,都知道服务器是个什么东西,以及服务器的作用、费用,相信都一清二楚。一般,我们用服务器说的简单点就是放一…

自动驾驶车载MCU开发修炼秘籍

目录 车载MCU开发修炼秘籍1、恩智浦 S32K1XX系列2、英飞凌 AURIX TC3XX3、嵌入式实时操作系统-FreeRTOS4、车载实时操作系统-AUTOSAR 车载MCU开发修炼秘籍 1、恩智浦 S32K1XX系列 S32K14X学习笔记&#xff08;一&#xff09;–S32K汽车MCU资源总结 S32K14X学习笔记&#xff1a…

启用Windows防火墙后,FTP传输非常慢

我们有一个计划任务&#xff0c;该任务使用Windows命令行FTP程序在两个Windows服务器之间传输大文件&#xff08;〜130 MB&#xff09;。速度很慢&#xff08;大约需要30分钟&#xff09;&#xff0c;有时会在传输完成之前终止。服务器是2003年&#xff08;发送&#xff09;和2…

chatgpt赋能python:Python主题设置——让你的网页更吸引人的秘诀

Python主题设置——让你的网页更吸引人的秘诀 近年来&#xff0c;Python在网页开发中的应用越来越广泛。不仅仅用于后端开发&#xff0c;Python也可以帮助我们设置网页主题&#xff0c;使得网页更加美观、易读、易用。本文将介绍Python主题设置的几个方面&#xff0c;帮助您让…

Redis学习手册(实例代码)

在下面的代码示例中&#xff0c;将给出两种最为常用的Redis命令操作方式&#xff0c;既普通调用方式和基于管线的调用方式。 注&#xff1a;在阅读代码时请留意注释。 1 #include <stdio.h>2 #include <stdlib.h>3 #include <stddef.h>4 #include <st…

git合并代码后,目录被删除了

问题&#xff1a; 同事x在a分支使用git checkout b -- test.md命令抽取b的文件&#xff0c;然后把代码合并到merge-c。 同事y在merge-c分支&#xff0c;合并了自己的分支b&#xff0c;然后拉取同事x的分支&#xff0c;发现产生了冲突&#xff0c;解决了冲突后提交。 最后发现自…