为摸鱼助力:一份Vue3的生成式ElementPlus表单组件

目录

一、实现背景

二、简介

三、组织架构设计 

四、实现方式

五、代码示例

六、示例代码效果预览

七、项目预览地址 & 项目源码地址

目前项目还有诸多待完善的地方,大家有好的想法、建议、意见等欢迎再次评论,或于github提交Issues


一、实现背景

        一切为了摸鱼而努力!!!

        在现代Web应用程序中,表单组件是不可或缺的一部分。但是,手动创建每个表单项是一个非常繁琐的过程。为此,我提供了一个基于Vue3的可配置的表单组件,帮助您快速构建表单,无需手动编写HTML或JavaScript代码。这篇文章将向您展示如何使用JSON配置文件一站式生成Vue3 Form表单组件,并在项目中使用它。

二、简介

        此表单组件是目前内嵌在一个基础项目中的,并没有作单独的npm包进行发布,因为目前是一个比较简单且基础的版本,需要优化的点还非常多。希望大家能多多提出宝贵的意见或建议,本文主要是针对实现思路等进行描述。

        目前实现功能:栅格化布局、监听单个表单数据变化、Form 表单除upload外的所有子组件。

        通过JSON配置一站式生成form表单,该组件保留了ElementPlus全部的使用习惯和使用方式,对ElementPlus原功能进行了完美的保留,支持所有属性设置(方法使用统一事件监听替代)

三、组织架构设计 

        在当前的表单组件中,数据层、UI层、事件层等模块相互独立,通过交互来协调和通信。

        其中,数据层负责存储和管理表单组件的数据;UI层负责渲染表单组件的外观;事件层负责处理用户与表单组件互动时的事件。通过这种方式,我们实现了一个高度可扩展和可重用的表单组件。

四、实现方式

        Vue3支持使用JSX/TSX语法,通过JSX/TSX(我这里使用的是TSX)进行不同表单组件的生成,枚举出Form表单的所有子组件。这里采用TSX的方式可以避免每一种组件都要去写一份Vue文件;

        通过匹配组件类型,生成对应的每一个表单组件;

        为保留ElementPlus组件所有属性,需要采用透传的方式,去列出每一个组件所可能用到的属性显然是不明智的;

        布局排版的生成采用el-row、el-col实现栅格布局,可通过配置进行动态调整;

        ElementPlus表单组件中的所有方法显然不是那么好处理的,因此使用同一个方法去监听每个表单项的变化,并提供给“用户”此时变化的key、newVal以及oldVal,这里采用Proxy进行了数据拦截;

        提供一个表单校验和重置表单数据的方法。

        某些ElementPlus表单组件中会提供一些插槽给用户使用,因此这些插槽也需要保留下来

组件生成示例:

case 'el-input':
    return (
        <ElInput
            type={elItem.specificType}
            {...elItem.bindObj}
            v-model={formData[elItem.key]}
            v-slots={itemInteriorSlotsObject}
        />
    )

五、代码示例

  • 配置项数据
const FormConfig = reactive({
    rowConfigBind: {
        gutter: 20,
        colSpan: 8
        // className: 'row-class'
    },
    formConfigBind: {
        labelPosition: 'top'
    },
    colsList: [
        {
            label: '一个普通的输入框',
            colSpan: 8,
            type: 'el-input',
            specificType: 'text',
            bindObj: {
                placeholder: '请输入文字',
                formatter: (value: any) => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ','),
                parser: (value: any) => value.replace(/\$\s?|(,*)/g, '')
            },
            key: 'name'
        },
        {
            label: '一个普通的输入框',
            htmlLabel:
                '<span class="customize-label-style">\n' +
                '            自定义tooltip效果\n' +
                '                <span class="tip-content-wrap">\n' +
                '                      <span class="tip-content">这是自己定义的tooltip</span>\n' +
                '                      <span class="triangle-style"></span>\n' +
                '                </span>\n' +
                '\n' +
                '        </span>\n',
            colSpan: 8,
            type: 'el-input',
            specificType: 'text',
            bindObj: {
                placeholder: '请输入文字',
                formatter: (value: any) => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ','),
                parser: (value: any) => value.replace(/\$\s?|(,*)/g, '')
            },
            key: 'name2'
        },
        {
            label: '添加了append文字的输入框',
            colSpan: 8,
            type: 'el-input',
            bindObj: {
                placeholder: '请输入'
            },
            rules: [
                {
                    required: true,
                    message: '请输入',
                    trigger: 'change'
                }
            ],
            slots: [
                {
                    name: 'append',
                    content: '.com'
                }
            ],
            key: 'comAdress'
        },
        {
            label: '添加了append JSX组件的输入框',
            colSpan: 8,
            type: 'el-input',
            bindObj: {
                placeholder: '请输入'
            },
            slots: [
                {
                    name: 'append',
                    content: TestTSXComp
                }
            ],
            key: 'appendJSXComp'
        },
        {
            label: '添加了append Vue组件的输入框',
            colSpan: 8,
            type: 'el-input',
            bindObj: {
                placeholder: '请输入'
            },
            slots: [
                {
                    name: 'append',
                    content: TestVueComp
                }
            ],
            key: 'appendVueComp'
        },
        {
            label: '数字输入框',
            colSpan: 4,
            type: 'el-input-number',
            bindObj: {
                placeholder: '请输入'
            },
            key: 'inputNumberVal'
        },
        {
            label: '测试表单生成函数',
            type: 'slots',
            key: 'content',
            colSpan: 24
        },
        {
            label: '下拉选',
            colSpan: 8,
            type: 'el-select',
            bindObj: {
                placeholder: '请选择',
                multiple: true
            },
            options: [
                {
                    label: '第一个选项',
                    value: 'A',
                    bindObj: {
                        disabled: true
                    }
                },
                {
                    label: '第二个选项',
                    value: 'B'
                },
                {
                    label: '第三个选项',
                    value: 'C'
                }
            ],
            key: 'optionValue'
        },
        {
            label: '单选框',
            colSpan: 8,
            type: 'el-radio',
            options: [
                {
                    label: '第一个选项',
                    value: 'A',
                    bindObj: {
                        disabled: true
                    }
                },
                {
                    label: '第二个选项',
                    value: 'B'
                },
                {
                    label: '第三个选项',
                    value: 'C'
                }
            ],
            key: 'radioValue'
        },
        {
            label: '按钮单选框',
            colSpan: 8,
            type: 'el-radio',
            bindObj: {
                textColor: 'red'
            },
            options: [
                {
                    label: '第一个选项',
                    value: 'A',
                    isButton: true
                },
                {
                    label: '第二个选项',
                    value: 'B',
                    isButton: true
                },
                {
                    label: '第三个选项',
                    value: 'C',
                    isButton: true // 如果是button样式展示,那么设置此属性为true
                }
            ],
            key: 'radioBtnValue'
        },
        {
            label: '自动补全输入框',
            colSpan: 8,
            type: 'el-autocomplete',
            bindObj: {},
            querySearchFun: querySearchFun,
            key: 'autocompleteValue'
        },
        {
            label: '日期选择框',
            colSpan: 8,
            type: 'el-date-picker',
            specificType: 'date',
            bindObj: {},
            key: 'detePickerValue'
        },
        {
            label: '日期时间选择框',
            colSpan: 8,
            type: 'el-date-picker',
            specificType: 'datetime',
            bindObj: {},
            key: 'deteTimePickerValue'
        },
        {
            label: '评分',
            colSpan: 8,
            type: 'el-rate',
            bindObj: {
                voidIcon: 'ChatRound',
                colors: ['#409eff', '#67c23a', '#FF9900'],
                icons: [ChatRound, ChatLineRound, ChatDotRound]
            },
            key: 'rateValue'
        },
        {
            label: '滑块',
            colSpan: 8,
            type: 'el-slider',
            bindObj: {
                showInput: true
            },
            key: 'elSliderValue'
        },
        {
            label: '开关',
            colSpan: 8,
            type: 'el-switch',
            bindObj: {
                style: '--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949'
            },
            key: 'elSwitchValue'
        },
        {
            label: '时间选择器',
            colSpan: 4,
            type: 'el-time-picker',
            key: 'timePickerValue'
        },
        {
            label: '时间选择',
            colSpan: 4,
            type: 'el-time-select',
            key: 'timeSelectValue'
        }
    ]
})
  • 表单数据
// 数据定义
const formData = reactive({
    name: '',
    comAdress: '',
    inputNumberVal: '',
    appendJSXComp: '',
    appendVueComp: '',
    optionValue: [],
    autocompleteValue: ''
})
  • 组件应用
<GenerateElForm
    ref="formInstance"
    :form-config="FormConfig"
    :form-data="formData"
    @updateFormValue="watcherFun"
>
    <template #content>
        <div class="form-slot-one">这是插槽的内容</div>
    </template>
</GenerateElForm>
  •  watcherFun
// 监听数据变化的方法
const watcherFun = (key: string, oldVal: any, newVal: any) => {
    console.log(
        '监听到数据变化',
        `当前变化的key是: ${key}, 它的旧值是: ${oldVal}, 它的新值是: ${newVal}`
    )
}

六、示例代码效果预览

七、项目预览地址 & 项目源码地址

项目预览地址:http://1.14.75.249/

项目源码地址:https://github.com/zuotiandeni/lcyBlog

目前项目还有诸多待完善的地方,大家有好的想法、建议、意见等欢迎再次评论,或于github提交Issues

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【吃透网络安全】2023软考网络管理员考点网络安全(三)计算机系统安全评估

涉及知识点 计算机系统安全评估准则&#xff0c;计算机系统安全评估历史&#xff0c;软考网络管理员常考知识点&#xff0c;软考网络管理员网络安全&#xff0c;网络管理员考点汇总。 后面还有更多续篇希望大家能给个赞哈&#xff0c;这边提供个快捷入口&#xff01; 第一节…

解决vue依赖报错SockJSServer.js出现Cannot read property ‘headers‘ of null

前言 在做新的需求需要变更vue的项目代码时突然出现报错 TypeError: Cannot read property ‘headers’ of null at Server.socket.on (***/node_modules/webpack-dev-server/lib/servers/SockJSServer.js:68:32) 不清楚为什么突然出现了这个问题&#xff0c;之前在这个vue项目…

【安全】使用docker安装Nessus

目录 一、准备docker环境服务器&#xff08;略&#xff09; 二、安装 2.1 搜索镜像 2.2 拉取镜像 2.3 启动镜像 三、离线更新插件 3.1 获取challenge 3.2 官方注册获取激活码 3.3 使用challenge码和激活码获取插件下载地址 3.4 下载的插件以及许可协议复制到容器内 四…

数据结构第六章 图 6.4 图的应用 错题整理

4.A A. 不是简单路径的话&#xff0c;有环&#xff0c;去环路径会更短 B. 适合的 弗洛伊德算法才不适合 C. 本来就是 D 2X2矩阵拓展到3X3矩阵 再扩大 若是子集 即加入新顶点后&#xff0c;最短路径都没有变&#xff0c;错 5.B 本题用弗洛伊德更合适 但这道题只需全部代入求最…

PowerShell系列(七)PowerShell当中的Provider介绍

往期回顾PowerShell系列&#xff08;一&#xff09;&#xff1a;PowerShell介绍和cmd命令行的区别 PowerShell系列&#xff08;二&#xff09;&#xff1a;PowerShell和Python之间的差异介绍 PowerShell系列&#xff08;三&#xff09;&#xff1a;PowerShell发展历程梳理 P…

@DateTimeFormat与@JsonFormat不完全解析

目录 前言测试代码DateTimeFormat不加任何注解的情况普通请求JSON请求 JsonFormat普通请求JSON请求 其他方式&#xff08;InitBinder&#xff09;结论源码地址 前言 一直以来对DateTimeFormat与JsonFormat 比较模糊&#xff0c;容易搞忘&#xff0c;今天就做个笔记&#xff0c…

UE4自定义资产类型编辑器实现

在虚幻引擎中&#xff0c;资产是具有持久属性的对象&#xff0c;可以在编辑器中进行操作。 Unreal 附带多种资源类型&#xff0c;从 UStaticMesh 到 UMetasoundSources 等等。 自定义资源类型是实现专门对象的好方法&#xff0c;这些对象需要专门构建的编辑器来进行高效操作。 …

SQL语言的四大组成部分——DCL(数据控制语言)

1️⃣前言 SQL语言中的DCL&#xff08;Data Control Language&#xff09;是一组用于控制数据库用户访问权限的语言&#xff0c;主要包括GRANT、REVOKE、DENY等关键字。 文章目录 1️⃣前言2️⃣DCL语言3️⃣GRANT关键字4️⃣REVOKE关键字5️⃣DENY关键字6️⃣总结附&#xff1…

【kubernetes】部署网络组件Calico与CoreDNS

前言:二进制部署kubernetes集群在企业应用中扮演着非常重要的角色。无论是集群升级,还是证书设置有效期都非常方便,也是从事云原生相关工作从入门到精通不得不迈过的坎。通过本系列文章,你将从虚拟机配置开始,到使用二进制方式从零到一搭建起安全稳定的高可用kubernetes集…

基于YOLO V8的车牌识别

赵春江 2023年6月 1、前言 十年前就想实现车牌识别这项任务&#xff0c;虽然当时这项技术就已较成熟&#xff08;与现在的实现方法不同&#xff09;&#xff0c;但那时的我还具备这个能力。弹指一瞬间&#xff0c;没想到十年间人工智能技术已经发展到一个新的高度&#xff0c…

Nacos架构与原理 - 健康检查机制

文章目录 注册中心的健康检查机制Nacos 健康检查机制临时实例健康检查机制永久实例健康检查机制集群模式下的健康检查机制 注册中心的健康检查机制 想象发生地质灾害,被掩埋在废墟下,搜救队需定位才能施救。两种方法: 大喊求救,告知位置与健康状况,让搜救队知晓搜救队使用专业…

社区活动 | OpenVINO™ DevCon 中国系列工作坊第二期 | 使用 OpenVINO™ 加速生成式 AI...

生成式 AI 领域一直在快速发展&#xff0c;许多潜在应用随之而来&#xff0c;这些应用可以从根本上改变人机交互与协作的未来。这一最新进展的一个例子是 GPT 模型的发布&#xff0c;它具有解决复杂问题的能力&#xff0c;比如通过医学和法律考试这种类似于人类的能力。然而&am…

CnOpenData数字经济专利申请与授权数据

一、数据简介 自人类社会进入信息时代以来&#xff0c;数字技术的快速发展和广泛应用衍生出数字经济。与农耕时代的农业经济、工业时代的工业经济大有不同&#xff0c;数字经济是一种新的经济、新的动能、新的业态&#xff0c;并引发了社会和经济的整体性深刻变革。现阶段&…

openEuler操作系统禁用 Nouveau

目录 一、什么是openEuler 二、什么是Nouveau 三、禁用Nouveau Liunx系统安装NVIDIA显卡驱动时需要禁用Nouveau&#xff0c;openEuler操作系统也不例外&#xff0c;但是网上openEuler操作系统如何禁用Nouveau的资料比较少&#xff0c;而且基本都不靠谱&#xff0c;我找到一个…

Keras-深度学习-神经网络-人脸识别模型

目录 模型搭建 模型训练 模型搭建 ①导入所需的库&#xff0c;导入了 Keras 和其他必要的库&#xff0c;用于构建和处理图像数据。 from keras.models import Sequential from keras.layers import Dense, Flatten, Conv2D, MaxPooling2D import os from PIL import Image …

streamlit——搭建学生评分网站(告别问卷星)

streamlit搭建多人评分网站 文章目录 streamlit搭建多人评分网站一、引言二、数据准备三、streamlit代码四、数据合并代码 一、引言 当需要对班级内多人进行打分时&#xff0c;为了不使用问卷星等平台进行评分&#xff0c;使用pandas进行操作数据&#xff0c;使用streamlit进行…

chatgpt赋能python:Python要点:从入门到精通

Python要点&#xff1a;从入门到精通 Python是一门高级编程语言&#xff0c;是一种解释型、面向对象、动态数据类型的语言。它的设计思想是“代码易读易写”&#xff0c;在数据科学、人工智能、自动化测试、Web开发等领域广泛应用。本文将从入门到精通的角度来介绍Python的要点…

内网穿透技术

文章目录 前言1. 安装JAVA2. MCSManager安装3.局域网访问MCSM4.创建我的世界服务器5.局域网联机测试6.安装cpolar内网穿透7. 配置公网访问地址8.远程联机测试9. 配置固定远程联机端口地址9.1 保留一个固定tcp地址9.2 配置固定公网TCP地址9.3 使用固定公网地址远程联机 转载自内…

自学黑客(网络安全),一般人我劝你还是算了吧(自学网络安全学习路线--第九章 Internet安全协议)【建议收藏】

文章目录 一、自学网络安全学习的误区和陷阱二、学习网络安全的一些前期准备三、自学网络安全学习路线一、安全协议概述二、IPSec协议1、概述2、IP封装过程3、IPSec不安全性4、IPSec的功能5、IPSec体系结构6、IPSec的AH7、IPSec的AH8、IPSec的ESP9、IPSec的ESP10、ISAKMP11、IK…

中职网络搭建(服务器)—Linux LVM(标准答案)

题目要求如下 使用fdisk-l查看磁盘信息 我们添加的磁盘分别是sdb和sdc Fdisk /dev/sdb 依次输入n,p,1&#xff0c;回车,2G &#xff08;新建2G的主分区&#xff09; 依次输入n,e,2&#xff0c;回车&#xff0c;回车&#xff08;使用剩余的全部空间建立扩展分区&#xff09; 依…