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年度…...

RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...
Webpack性能优化:构建速度与体积优化策略
一、构建速度优化 1、升级Webpack和Node.js 优化效果:Webpack 4比Webpack 3构建时间降低60%-98%。原因: V8引擎优化(for of替代forEach、Map/Set替代Object)。默认使用更快的md4哈希算法。AST直接从Loa…...

基于Springboot+Vue的办公管理系统
角色: 管理员、员工 技术: 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能: 该办公管理系统是一个综合性的企业内部管理平台,旨在提升企业运营效率和员工管理水…...
Bean 作用域有哪些?如何答出技术深度?
导语: Spring 面试绕不开 Bean 的作用域问题,这是面试官考察候选人对 Spring 框架理解深度的常见方式。本文将围绕“Spring 中的 Bean 作用域”展开,结合典型面试题及实战场景,帮你厘清重点,打破模板式回答,…...

水泥厂自动化升级利器:Devicenet转Modbus rtu协议转换网关
在水泥厂的生产流程中,工业自动化网关起着至关重要的作用,尤其是JH-DVN-RTU疆鸿智能Devicenet转Modbus rtu协议转换网关,为水泥厂实现高效生产与精准控制提供了有力支持。 水泥厂设备众多,其中不少设备采用Devicenet协议。Devicen…...

嵌入式学习之系统编程(九)OSI模型、TCP/IP模型、UDP协议网络相关编程(6.3)
目录 一、网络编程--OSI模型 二、网络编程--TCP/IP模型 三、网络接口 四、UDP网络相关编程及主要函数 编辑编辑 UDP的特征 socke函数 bind函数 recvfrom函数(接收函数) sendto函数(发送函数) 五、网络编程之 UDP 用…...

Kubernetes 节点自动伸缩(Cluster Autoscaler)原理与实践
在 Kubernetes 集群中,如何在保障应用高可用的同时有效地管理资源,一直是运维人员和开发者关注的重点。随着微服务架构的普及,集群内各个服务的负载波动日趋明显,传统的手动扩缩容方式已无法满足实时性和弹性需求。 Cluster Auto…...
2025年低延迟业务DDoS防护全攻略:高可用架构与实战方案
一、延迟敏感行业面临的DDoS攻击新挑战 2025年,金融交易、实时竞技游戏、工业物联网等低延迟业务成为DDoS攻击的首要目标。攻击呈现三大特征: AI驱动的自适应攻击:攻击流量模拟真实用户行为,差异率低至0.5%,传统规则引…...