当前位置: 首页 > news >正文

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的所有属性

参数说明类型默认值
refObjform 表单校验规则方法 (可以参考 antd FormModel 表单方法中的 validate)obj-
className自定义类名String-
layout改变表单项 label 与输入框的布局方式(默认:horizontal) /verticalString‘horizontal’
widthSize每行显示几个输入项(默认两项) 最大值 4Number2
isTrim全局是否开启清除前后空格(comp 为 a-input 且 type 不等于’password’)Booleantrue
formOpts表单配置项Object{}
—listTypeInfo下拉选择数据源(type:'select’有效)Object{}
—fieldListform 表单每项 listArray[]
------isHideItem某一项不显示Booleanfalse
------slotName自定义表单某一项输入框slot-
------childSlotName自定义表单某一下拉选择项子组件插槽(a-select-option)slot-
------compform 表单每一项组件是输入框还是下拉选择等(可使用第三方 UI 如 a-select/a-input 也可以使用自定义组件)String-
------formItemBind表单每一项属性(继承FormModelItem的 Attributes)Object{}
------bind表单每一项属性(继承第三方 UI 的 Attributes,如 a-input 中的 allowClear 清空功能)默认清空及下拉过滤Object{}
------isTrim是否不清除前后空格(comp 为 a-input 且 type 不等于’password’)Booleanfalse
------typeform 表单每一项类型String-
------widthSizeform 表单某一项所占比例(如果占一整行则设置 1)Number2
------widthform 表单某一项所占实际宽度String100%
------arrLabeltype=select-arr 时,每个下拉显示的中文String‘label’
------arrKeytype=select-arr 时,每个下拉显示的中文传后台的数字String‘value’
------labelform 表单每一项 titleString-
------labelRender自定义某一项 titlefunction-
------valueform 表单每一项传给后台的参数String-
------rules每一项输入框的表单校验规则Object/Array-
------list下拉选择数据源(仅仅对 type:'select’有效)String-
------event表单每一项事件标志(handleEvent 事件)String-
------eventHandle继承 comp 组件的事件(返回两个参数,第一个自己自带,第二个 formOpts)Object-
------isSelfCom是否使用自己封装的组件(TAntdSelect等—含有下拉框)Booleanfalse
—formData表单提交数据(对应 fieldList 每一项的 value 值)Object-
—labelCollabel 宽度({ span:2})Object{span:2}
—wrapperCol输入框 宽度Object{span:22}
—rules规则(可依据 AntdUI FormModel 配置————对应 formData 的值)Object/Array-
—operatorList操作按钮 listArray-

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再次封装基础组件文档

http://www.lryc.cn/news/214568.html

相关文章:

  • 对比解析php和go对JSON处理的区别
  • HTTP和HTTPS本质区别——SSL证书
  • JS 防抖和节流
  • Django开发实例总结(入门级、4.2.6、详细)
  • Variations-of-SFANet-for-Crowd-Counting可视化代码
  • 所有的人机交互都存在不匹配现象
  • LED数码管的静态显示与动态显示(Keil+Proteus)
  • webGL编程指南 第五章 TexturedQuad_Clamp_Mirror
  • 【Azure】存储服务:Azure 的存储账户
  • 高等数学啃书汇总重难点(十一)曲线积分与曲面积分
  • 【算法专题】双指针—盛最多水的容器
  • java入门,程序=数据结构+算法
  • 9.MySQL索引的操作
  • 大型加油站3d全景虚拟现实展示平台实现全方位立体呈现
  • Reading:Deep dive into the OnPush change detection strategy in Angular
  • 野火霸天虎 STM32F407 学习笔记_1 stm32介绍;调试方法介绍
  • @reduxjs/toolkit配置react-redux解决createStore或将在未来被淘汰警告
  • 致敬1024天前的自己
  • 〖Python网络爬虫实战㊱〗- JavaScript 网站加密和混淆
  • 基于单片机设计的电子柜锁
  • Windows安装tensorflow-gpu=1.14.0CUDA=10.0cuDNN=7.4 (多版本CUDA共存)
  • CodeWhisperer 初体验
  • HNU-算法设计与分析-讨论课1
  • java连接zookeeper
  • 2023-11-01 node.js-electron-环境配置-记录
  • 使用 ElementUI 组件构建 Window 桌面应用探索与实践(WinForm)
  • 使用C++构建安全队列
  • EasyFlash移植使用- 关于单片机 BootLoader和APP均使用的情况
  • python捕获异常和scapy模块的利用
  • CSS+Javascript+Html日历控件