vue2+ant-design-vue a-form-model组件二次封装(form表单组件)FormModel 表单
一、效果图

二、参数配置
1、代码示例
<t-antd-form:ref-obj.sync="formOpts.ref":formOpts="formOpts":widthSize="1":labelCol="{ span:2}":wrapperCol="{ span:22}"@handleEvent="handleEvent"
/>
2. 配置参数继承FormModel的所有属性
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| refObj | form 表单校验规则方法 (可以参考 antd FormModel 表单方法中的 validate) | obj | - |
| className | 自定义类名 | String | - |
| layout | 改变表单项 label 与输入框的布局方式(默认:horizontal) /vertical | String | ‘horizontal’ |
| widthSize | 每行显示几个输入项(默认两项) 最大值 4 | Number | 2 |
| isTrim | 全局是否开启清除前后空格(comp 为 a-input 且 type 不等于’password’) | Boolean | true |
| formOpts | 表单配置项 | Object | {} |
| —listTypeInfo | 下拉选择数据源(type:'select’有效) | Object | {} |
| —fieldList | form 表单每项 list | Array | [] |
| ------isHideItem | 某一项不显示 | Boolean | false |
| ------slotName | 自定义表单某一项输入框 | slot | - |
| ------childSlotName | 自定义表单某一下拉选择项子组件插槽(a-select-option) | slot | - |
| ------comp | form 表单每一项组件是输入框还是下拉选择等(可使用第三方 UI 如 a-select/a-input 也可以使用自定义组件) | String | - |
| ------formItemBind | 表单每一项属性(继承FormModelItem的 Attributes) | Object | {} |
| ------bind | 表单每一项属性(继承第三方 UI 的 Attributes,如 a-input 中的 allowClear 清空功能)默认清空及下拉过滤 | Object | {} |
| ------isTrim | 是否不清除前后空格(comp 为 a-input 且 type 不等于’password’) | Boolean | false |
| ------type | form 表单每一项类型 | String | - |
| ------widthSize | form 表单某一项所占比例(如果占一整行则设置 1) | Number | 2 |
| ------width | form 表单某一项所占实际宽度 | String | 100% |
| ------arrLabel | type=select-arr 时,每个下拉显示的中文 | String | ‘label’ |
| ------arrKey | type=select-arr 时,每个下拉显示的中文传后台的数字 | String | ‘value’ |
| ------label | form 表单每一项 title | String | - |
| ------labelRender | 自定义某一项 title | function | - |
| ------value | form 表单每一项传给后台的参数 | String | - |
| ------rules | 每一项输入框的表单校验规则 | Object/Array | - |
| ------list | 下拉选择数据源(仅仅对 type:'select’有效) | String | - |
| ------event | 表单每一项事件标志(handleEvent 事件) | String | - |
| ------eventHandle | 继承 comp 组件的事件(返回两个参数,第一个自己自带,第二个 formOpts) | Object | - |
| ------isSelfCom | 是否使用自己封装的组件(TAntdSelect等—含有下拉框) | Boolean | false |
| —formData | 表单提交数据(对应 fieldList 每一项的 value 值) | Object | - |
| —labelCol | label 宽度({ span:2}) | Object | {span:2} |
| —wrapperCol | 输入框 宽度 | Object | {span:22} |
| —rules | 规则(可依据 AntdUI FormModel 配置————对应 formData 的值) | Object/Array | - |
| —operatorList | 操作按钮 list | Array | - |
3. events继承FormModel的所有事件
| 事件名 | 说明 | 返回值 |
|---|---|---|
| handleEvent | 单个查询条件触发事件 | fieldList 中 type/查询条件输入的值/fieldList 中 event 值 |
4. Methods
| 事件名 | 说明 | 参数 |
|---|---|---|
| resetFields | 重置表单 | - |
| clearValidate | 清空校验 | - |
5. 关于 Ant-Design-Vue FormModel/FormModelItem 提供的一些属性可直接使用,无需其他配置
三、源码
<template><FormModelref="form"class="t_antd_form":class="className":model="formOpts.formData":rules="formOpts.rules":layout="formOpts.layout||'horizontal'"v-bind="formAttr"v-on="$listeners"><template v-for="(item, index) in fieldList"><FormModelItemv-if="!item.isHideItem":key="index":prop="item.value":label="item.label":class="[item.className]":rules="item.rules":style="getChildWidth(item)"v-bind="{...item.formItemBind}"><!-- 自定义label --><template #label v-if="item.labelRender"><render-comp :createElementFunc="item.labelRender" /></template><!-- 自定义输入框插槽 --><template v-if="item.slotName"><slot :name="item.slotName"></slot></template><!-- 文本展示值 --><template v-if="item.textShow"><span>{{item.textValue||formOpts.formData[item.value]}}</span></template><template v-if="item.isSelfCom"><component:is="item.comp"v-model="formOpts.formData[item.value]":placeholder="item.placeholder||getPlaceholder(item)"v-bind="{allowClear:true,showSearch:true,...item.bind}":style="{width: item.width||'100%'}"v-on="cEvent(item)"/></template><componentv-if="!item.slotName&&!item.textShow&&!item.isSelfCom":is="item.comp"v-model="formOpts.formData[item.value]":type="item.type||item.bind.type":mode="item.comp.includes('picker')?(item.type||item.bind.type):''":placeholder="item.placeholder||getPlaceholder(item)"@change="handleEvent(item.event, formOpts.formData[item.value],item)"v-bind="{allowClear:true,showSearch:true,...item.bind}":style="{width: item.width||'100%'}"v-on="cEvent(item)"><template #addonBefore v-if="item.addonBefore">{{ item.addonBefore }}</template><template #addonAfter v-if="item.addonAfter">{{ item.addonAfter }}</template><template v-if="item.childSlotName"><slot :name="item.childSlotName"></slot></template><componentv-else:is="compChildName(item)"v-for="(value, key, index) in selectListType(item)":key="index":disabled="value.disabled":label="compChildLabel(item,value)":value="compChildValue(item,value,key)">{{compChildShowLabel(item,value)}}</component></component></FormModelItem></template><!-- 按钮 --><div class="footer_btn"><template v-if="formOpts.btnSlotName"><slot :name="formOpts.btnSlotName"></slot></template><template v-if="!formOpts.btnSlotName&&formOpts.operatorList&&formOpts.operatorList.length>0"><Buttonv-for="(val,index) in formOpts.operatorList":key="index"@click="val.fun(val)":type="val.type||'primary'":icon="val.icon":size="val.size || 'default'":disabled="val.disabled">{{ val.label }}</Button></template></div></FormModel>
</template>
<script>
import RenderComp from './render-comp.vue'
import { FormModel, Button } from 'ant-design-vue'
export default {name: 'TAntdForm',components: {RenderComp,FormModel,FormModelItem: FormModel.Item,Button},props: {/** 表单配置项说明* formData object 表单提交数据* rules object 验证规则* fieldList Array 表单渲染数据* operatorList Array 操作按钮list* listTypeInfo object 下拉选项数据*/formOpts: {type: Object,default: () => ({})},// 自定义类名className: {type: String},// 一行显示几个输入项;最大值4widthSize: {type: Number,default: 2,validator: (value) => {return value <= 4}},// 全局是否开启清除前后空格isTrim: {type: Boolean,default: true},// refrefObj: {type: Object}},data() {return {colSize: this.widthSize,fieldList: this.formOpts.fieldList}},computed: {formAttr() {let attr = {}this.formOpts.layout === 'vertical'? attr = {...this.$attrs} : attr = {labelCol: { span: 2 },wrapperCol: { span: 22 },...this.$attrs}return attr},cEvent() {return ({ eventHandle }, type) => {let event = { ...eventHandle }let changeEvent = {}Object.keys(event).forEach(v => {changeEvent[v] = (e, ids) => {if (type === 't-antd-select-table') {event[v] && event[v](e, ids, arguments)} else {if ((typeof e === 'number' && e === 0) || e) {event[v] && event[v](e, this.formOpts, arguments)} else {event[v] && event[v](this.formOpts, arguments)}}}})return { ...changeEvent }}},selectListType() {return ({ list }) => {if (this.formOpts.listTypeInfo) {return this.formOpts.listTypeInfo[list]} else {return []}}},// 子组件名称compChildName() {return ({ type }) => {switch (type) {case 'checkbox':return 'a-checkbox'case 'radio':return 'a-radio'case 'select-arr':case 'select-obj':return 'a-select-option'}}},// 子子组件labelcompChildLabel() {return ({ type, arrLabel }, value) => {switch (type) {case 'radio':case 'checkbox':return value.valuecase 'select-arr':return value[arrLabel || 'label']case 'select-obj':return value}}},// 子子组件valuecompChildValue() {return ({ type, arrKey }, value, key) => {switch (type) {case 'radio':case 'checkbox':return value.valuecase 'select-arr':return value[arrKey || 'value']case 'select-obj':return key}}},// 子子组件文字展示compChildShowLabel() {return ({ type, arrLabel }, value) => {switch (type) {case 'radio':case 'checkbox':return value.labelcase 'select-arr':return value[arrLabel || 'label']case 'select-obj':return value}}}},watch: {'formOpts.formData': {handler(val) {// 将form实例返回到父级this.$emit('update:refObj', this.$refs.form)},deep: true // 深度监听},widthSize(val) {if (val > 4) {this.$message.warning('widthSize值不能大于4!')this.colSize = 4} else {this.colSize = val}}},mounted() {// 将form实例返回到父级this.$emit('update:refObj', this.$refs.form)},methods: {// label与输入框的布局方式getChildWidth(item) {if (this.formOpts.layout === 'vertical') {return `flex: 0 1 calc((${100 / (item.widthSize || this.colSize)}% - 10px));margin-right:10px;`} else {return `flex: 0 1 ${100 / (item.widthSize || this.colSize)}%;`}},// 得到placeholder的显示getPlaceholder(row) {let placeholderif (typeof row.comp === 'string' && row.comp) {if (row.comp.includes('input')) {placeholder = row.label ? `请输入${row.label}` : `请输入`} else if (row.comp.includes('select') || row.comp.includes('cascader')) {placeholder = row.label ? `请选择${row.label}` : `请选择`} else if (!row.comp.includes('t-antd-date-picker')) {placeholder = row.label}} else {placeholder = row.label}return placeholder},// 绑定的相关事件handleEvent(type, val, item) {// console.log('组件', type, val, item)// 去除前后空格if (this.isTrim && !item.isTrim && item.comp.includes('input') && item.type !== 'password' && item.type !== 'inputNumber') {this.formOpts.formData[item.value] = this.formOpts.formData[item.value].trim()}this.$emit('handleEvent', type, val)},validate() {// selfValidate() {return new Promise((resolve, reject) => {this.$refs.form.validate(valid => {if (valid) {resolve({valid,formData: this.formOpts.formData})} else {// eslint-disable-next-line prefer-promise-reject-errorsreject({valid,formData: null})}})})},// 重置表单resetFields() {return this.$refs.form.resetFields()},// 清空校验clearValidate() {return this.$refs.form.clearValidate()}}
}
</script>
<style lang="scss">
.t_antd_form {display: flex;flex-wrap: wrap;.ant-select,.ant-calendar-picker {width: 100%;}.footer_btn {display: flex;align-items: center;justify-content: center;margin-top: 5px;width: 100%;.ant-btn {margin-left: 10px;}.ant-btn:first-child {margin-left: 0;}}
}
</style>
四、组件地址
gitHub组件地址
gitee码云组件地址
五、相关文章
基于ElementUi再次封装基础组件文档
基于ant-design-vue再次封装基础组件文档
vue3+ts基于Element-plus再次封装基础组件文档
相关文章:
vue2+ant-design-vue a-form-model组件二次封装(form表单组件)FormModel 表单
一、效果图 二、参数配置 1、代码示例 <t-antd-form:ref-obj.sync"formOpts.ref":formOpts"formOpts":widthSize"1":labelCol"{ span:2}":wrapperCol"{ span:22}"handleEvent"handleEvent" />2. 配置参数…...
对比解析php和go对JSON处理的区别
一、go 转化php数组代码 php程序 $str <<<EOF {"操作源":"任意","数据库":"任意","语句类型":"CREATE DATABASE;DROP DATABASE;ALTER DATABASE","影响行数":"不…...
HTTP和HTTPS本质区别——SSL证书
HTTP和HTTPS是两种广泛使用的协议,尽管它们看起来很相似,但是它们在网站数据传输的安全性上有着本质上的区别。 HTTP是明文传输协议,意味着通过HTTP发送的数据是未经加密的,容易受到拦截、窃听和篡改的风险。而HTTPS通过使用SSL或…...
JS 防抖和节流
防抖(debounce)和节流(throttle)是JavaScript中常用的性能优化技术,用于限制某些高频率触发的函数执行次数,减少不必要的计算和网络请求。下面分别介绍防抖和节流的实现方式。 防抖(Debounce&am…...
Django开发实例总结(入门级、4.2.6、详细)
目录 概述 Django的核心组件包括 Django的项目结构 创建工程(4.2.6) 实例一:Hello world 实例二:访问一个自定义主页 实例三:通过登录跳转到主页 实例四:主页添加静态文件,包含js、css、…...
Variations-of-SFANet-for-Crowd-Counting可视化代码
前文对Variations-of-SFANet-for-Crowd-Counting做了一点基础梳理,链接如下:Variations-of-SFANet-for-Crowd-Counting记录-CSDN博客 本次对其中两个可视化代码进行梳理 1.Visualization_ShanghaiTech.ipynb 不太习惯用jupyter notebook, 这里改成了p…...
所有的人机交互都存在不匹配现象
从接受理论的角度来看,就像夫妻一样,所有的人机交互都存在不匹配的现象。 接受理论是一个解释人们如何学习和接受信息的心理模型。该理论认为,当人们学习新信息时,他们会将其与自己已有的知识和经验联系起来,以便更好地…...
LED数码管的静态显示与动态显示(Keil+Proteus)
前言 就是今天看了一下书上的单片机实验,发现很多的器件在Proteus中都不知道怎么去查找,然后想做一下这个实验,尝试能不能实现,LED数码管的两个还可以实现,但是用LED点阵显示器的时候他那个网络标号不知道是什么情况&…...
webGL编程指南 第五章 TexturedQuad_Clamp_Mirror
我会持续更新关于wegl的编程指南中的代码。 当前的代码不会使用书中的缩写,每一步都是会展开写。希望能给后来学习的一些帮助 git代码地址 :空 上一章节中我们学习了如何使用varyting变量绘制图片,本章节,我们学习texParameter…...
【Azure】存储服务:Azure 的存储账户
文章目录 一、前提知识(建议了解)二、介绍 Azure 存储帐户三、使用 Microsoft Azure 门户创建存储帐户 一、前提知识(建议了解) 在每一个云厂商中,都有自身的云存储,也有根据不同功能进行区分的不同类型的…...
高等数学啃书汇总重难点(十一)曲线积分与曲面积分
依旧是公式极其复杂恶心的一章,建议是:掌握两种线面积分的计算套路即可,和第8章一样属于同济版教材中最不重要的章节,不会对底层理解做过多考察~ 1.弧长曲线积分的几何意义 2.弧长曲线积分的定义和性质 3.弧长曲线积分的计算方式 …...
【算法专题】双指针—盛最多水的容器
一、题目解析 分析这个题目不难得出一个容积公式 二、算法原理 解法一:暴力枚举(超时) 套用上述的容积公式,使用两个for循环来枚举出所有可能的情况,再挑出最大值即可,但是这种写法会超时,导致…...
java入门,程序=数据结构+算法
一、前言 在学习java的时候,我印象最深的一句话是:程序数据结构算法,对于写java程序来说,这就是java的入门。 二、java基本数据结构与算法 1、数据类型 java中的数据类型8种基本数据类型: 整型 byte 、short 、int…...
9.MySQL索引的操作
个人主页:Lei宝啊 愿所有美好如期而遇 目录 索引操作 查询索引 创建主键索引 唯一索引的创建 普通索引的创建 全文索引的创建 删除索引 索引创建原则 索引操作 查询索引 第一种方法: show keys from 表名\G 我们了解其中几个就好。 第二种方法…...
大型加油站3d全景虚拟现实展示平台实现全方位立体呈现
近年来,随着国民经济的快速发展,交通基础设施的不断改善,机动车保有量的持续飙升,以至于加油站的建设数量和密度也在不断扩张。加油站作为人流量大且常见的城市场景,对加油站进行安全防范措施具有非常重要的安全意义。…...
Reading:Deep dive into the OnPush change detection strategy in Angular
原文连接:IndepthApp 今天深入阅读并总结Angualr中onPush更新策略。 1. 两种策略 & whats Lview? Angular 实现了两种策略来控制各个组件级别的更改检测行为。这些策略定义为Default和OnPush: 被定义为枚举: export enum…...
野火霸天虎 STM32F407 学习笔记_1 stm32介绍;调试方法介绍
STM32入门——基于野火 F407 霸天虎课程学习 前言 博主开始探索嵌入式以来,其实很早就开始玩 stm32 了。但是学了一段时间之后总是感觉还是很没有头绪,不知道在学什么。前前后后分别尝试了江协科技、正点原子、野火霸天虎三次 stm32 的课程学习。江协科…...
@reduxjs/toolkit配置react-redux解决createStore或将在未来被淘汰警告
通常 我们用redux都需要通过 createStore 但目前 你去用它 基本都会被划线 甚至有点厉害的的编辑器 他会直接告诉你这个东西基本快被弃用了 这个应该大家都知道 最好不要用已经被明确未来或弃用的语法 因为一旦弃用这个系统就需要维护 而且说 一般会被淘汰的语法 本身也就是有…...
致敬1024天前的自己
今早打开手机就收到了来自CSDN的消息,哦,距离我发表第一篇技术博客已经过去1024个日夜了。 我第一次发技术博客是我大二做完我第一个网站时写的。因为网站需要上线服务器,涉及到不少linux相关的知识,我在自学的过程中走了不少弯路…...
〖Python网络爬虫实战㊱〗- JavaScript 网站加密和混淆
订阅:新手可以订阅我的其他专栏。免费阶段订阅量1000+python项目实战 Python编程基础教程系列(零基础小白搬砖逆袭) 说明:本专栏持续更新中,订阅本专栏前必读关于专栏〖Python网络爬虫实战〗转为付费专栏的订阅说明作者:爱吃饼干的小白鼠。Python领域优质创作者,2022年度…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
质量体系的重要
质量体系是为确保产品、服务或过程质量满足规定要求,由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面: 🏛️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限,形成层级清晰的管理网络…...
JDK 17 新特性
#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持,不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的ÿ…...
sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...
佰力博科技与您探讨热释电测量的几种方法
热释电的测量主要涉及热释电系数的测定,这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中,积分电荷法最为常用,其原理是通过测量在电容器上积累的热释电电荷,从而确定热释电系数…...
算法:模拟
1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) 遍历字符串:通过外层循环逐一检查每个字符。遇到 ? 时处理: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: 与…...
【网络安全】开源系统getshell漏洞挖掘
审计过程: 在入口文件admin/index.php中: 用户可以通过m,c,a等参数控制加载的文件和方法,在app/system/entrance.php中存在重点代码: 当M_TYPE system并且M_MODULE include时,会设置常量PATH_OWN_FILE为PATH_APP.M_T…...
React核心概念:State是什么?如何用useState管理组件自己的数据?
系列回顾: 在上一篇《React入门第一步》中,我们已经成功创建并运行了第一个React项目。我们学会了用Vite初始化项目,并修改了App.jsx组件,让页面显示出我们想要的文字。但是,那个页面是“死”的,它只是静态…...
