记录一下开发中对form表单的二次封装及使用


前言

在我们的日常工作中经常会使用到form表来满足提交需求,那么将form表单封装成组件将会大大提高我们的工作效率,避免更多重复代码的书写,只需一些简单的配置就轻松实现。


一、form表单的封装

<template><div class='form'><el-form:label-position="labelPosition":inline="inline":rules="rules"ref="formRef":label-width="labelWidth":model="fieldForm":class="customClass"><el-form-itemv-for="(item, index) in fieldList":key="index":prop="item.field":validate-on-rule-change="false":style="{flexBasis: item.percent ? item.percent : item.percent ?     `${item.percent}%!important` : '',width: item.width && isNaN(Number(item.width)) ? item.width +'!important'|| '' : item.width + 'px!important' || '',}":class="[item.className || '', `is-${item.formType}`]":rules="getRules(item)"><template#labelv-if="item.name"><div style="display: inline"><a :style="{ color: item.labelColor || '' }">{{ item.name || '' }}</a></div></template><template v-if="item.formType && item.mold && !item.hidden"><component:is="com['M' + item.mold]"v-model="fieldForm[item.field]":item="item":index="index":disabled="disabled":size="size":field-form="fieldForm"@change="commonChange"/></template></el-form-item></el-form></div>
</template>
<script lang="ts" setup>
import { toRefs } from 'vue';
//引入组件
import MInput from './components/MInput.vue';
import MDate from './components/MDate.vue';
import MSelect from './components/MSelect.vue';//这是自定义表单验证规则
import GenerateRules from './GenerateRules.ts';//接收父组件传递的参数
const props = defineProps({customClass: {type: String,default: 'is-three-columns',},rules: {type: Object,default: () => {return {};},},fieldForm: {type: Object,default: () => {return {};},},labelWidth: {type: Number,default: 90},fieldList: {type: Array,default: () => [],},// 行内表单inline: {type: Boolean,default: false,},// 对齐方式 'right' | 'left' | 'top'labelPosition: {type: String,default: 'right',},size: {type: String,default: 'default',},disabled: {type: Boolean,default: false,},
});
const { customClass, rules, fieldForm, labelWidth, fieldList } = toRefs(props);// 定义组件
const com: Record<string, any> = {MInput: MInput,MDate: MDate,MSelect: MSelect,
};//事件传递
const $emit = defineEmits(['change']);/*** 常规组件change事件* @param item 配置数据* @param index 下标* @param value 选中/输入的值* @param data 选中的整条数据*/
const commonChange = (item, index, value, data) => {$emit('change', item, index, value, data);
};//自定义验证规则
const { getRules } = GenerateRules();</script>

二、components

1.MDate.vue

代码如下(示例):

<template><el-date-pickerv-if="item.formType == 'date'"v-model="fieldForm[item.field]":disabled="item.disabled || disabled"clearablestyle="width: 100%"type="date":size="size":editable="true"value-format="YYYY-MM-DD":placeholder="item.placeholder || '选择日期'"@click.stop@change="commonChange(item, index, $event)"/><el-date-pickerv-else-if="item.formType == 'month'"v-model="fieldForm[item.field]":disabled="item.disabled || disabled"clearablestyle="width: 100%"type="month":size="size"value-format="YYYY-MM":placeholder="item.placeholder || '选择月份'"@change="commonChange(item, index, $event)"/><el-date-pickerv-else-if="item.formType == 'year'"v-model="fieldForm[item.field]":disabled="item.disabled || disabled"clearablestyle="width: 100%"type="year":size="size"value-format="YYYY":placeholder="item.placeholder || '选择年份'"@change="commonChange(item, index, $event)"/><el-date-pickerv-else-if="item.formType == 'dateRange'"v-model="fieldForm[item.field]":disabled="item.disabled || disabled":type="item.dateType || 'daterange'":value-format="item.dateValueFormat || 'YYYY-MM-DD'":picker-options="item.pickerOptions || ''"clearable:size="size"style="width: 100%":start-placeholder="item.startPlaceholder || '开始日期'":end-placeholder="item.endPlaceholder || '结束日期'"@change="commonChange(item, index, $event)"/><el-date-pickerv-else-if="item.formType == 'datetime'"v-model="fieldForm[item.field]":disabled="item.disabled || disabled"clearablestyle="width: 100%":size="size"type="datetime"value-format="YYYY-MM-DD HH:mm:ss":placeholder="item.placeholder || '选择日期'"@change="commonChange(item, index, $event)"/>
</template>
<script lang="ts" setup>
import { toRefs, PropType } from 'vue';
import Hooks from '../Hooks.ts';
// 定义defineProps
const props = defineProps({modelValue: {type: [Number, String],default: '',},item: {type: Object,default: () => {},},disabled: {type: Boolean,default: false,},size: {type: String as PropType <''| 'large' | 'small'>,default: 'small',},index: {type: Number,default: null,},fieldForm: {type: Object,default: () => {},},
});
const { fieldForm } = toRefs(props);// 定义$emit
const $emit = defineEmits(['change']);const { commonChange } = Hooks($emit);
</script>

2.MInput.vue

代码如下(示例):

<template><el-inputv-if="item.formType == 'text' && !item.hidden"v-model="fieldForm[item.field]":size="size || ''":disabled="item.disabled || disabled":maxlength="item.maxlength":placeholder="item.placeholder":type="item.formType":show-word-limit="item.showLimit":title="fieldForm[item.field]"clearable:readonly="item.readonly":name="item.field"@input="commonChange(item, index, $event)"/><el-input-numberv-else-if="['floatnumber', 'number'].includes(item.formType)"v-model="fieldForm[item.field]":placeholder="item.placeholder":disabled="item.disabled || disabled":controls="item.controls || false":controls-position="item.position || 'right'"clearable:size="size"@change="commonChange(item, index, $event)"/><el-inputv-else-if="item.formType === 'textarea'"v-model="fieldForm[item.field]":disabled="item.disabled || disabled":rows="item.rows || 2":autosize="!item.autosize && { minRows: item.rows || 2 }":maxlength="item.maxlength || 800":placeholder="item.placeholder":type="item.formType"clearable:size="size":resize="item.resize || 'none'"@input="commonChange(item, index, $event)"/>
</template>
<script lang="ts" setup>
import { toRefs} from 'vue';
import Hooks from '../Hooks.ts';// 定义props
const props = defineProps({modelValue: {default: '',},item: {type: Object,default: () => {},},disabled: {type: Boolean,default: false,},size: {type: String,default: 'small',},index: {type: Number,default: null,},fieldForm: {type: Object,default: () => {},},
});
const { fieldForm } = toRefs(props);// 定义$emit
const $emit = defineEmits(['change']);const { commonChange } = Hooks($emit);
</script>

3.MInput.vue

代码如下(示例):

<template><el-selectv-if="item.formType == 'select'"v-model="fieldForm[item.field]":disabled="item.disabled || disabled":clearable="item.clearable || true":placeholder="item.placeholder":multiple="item.multiple":collapse-tags="item.collapse":collapse-tags-tooltip="item.tooltip":size="size":value-key="item.props?.valueKey || 'id'"filterablestyle="width: 100%"@change="commonChange(item, index, $event)"><el-optionv-for="(items, i) in item.basicGroup? getGroupValue(item): item.setting":key="i":label="!isEmptyValue(items[item.props?.value || 'value']) ?                 items[item.props?.label || 'label'] || items.name : items":value="!isEmptyValue(items[item.props?.value || 'value']) ? items[item.props?.value || 'value'] : items"/></el-select><el-radio-groupv-else-if="item.formType == 'radio-group'":size="size":disabled="item.disabled || disabled"v-model="fieldForm[item.field]"@change="commonChange(item, index, $event)"><el-radio:label="items.value"v-for="(items, i) in item.setting":key="i">{{ items.label }}</el-radio></el-radio-group><el-switchv-else-if="item.formType == 'switch'"v-model="fieldForm[item.field]"inline-prompt:size="size":active-color="item.active&&item.active.color || '#67c23a'":inactive-color="item.inactive&&item.inactive.color || '#f56c6c'":active-text="item.active&&item.active.text || '是'":inactive-text="item.inactive&&item.inactive.text || '否'"/><el-checkbox-groupv-else-if="item.formType == 'checkbox-group'":size="size":disabled="item.disabled || disabled"v-model="fieldForm[item.field]"@change="commonChange(item, index, $event)"><el-checkbox:label="items.label"v-for="(items, i) in item.setting":key="i"/></el-checkbox-group>
</template>
<script lang="ts" setup>
import Hooks from '../Hooks.ts';
import { toRefs} from 'vue';// 定义props
const props = defineProps({modelValue: {default: '',},item: {type: Object,default: () => { },},disabled: {type: Boolean,default: false,},size: {type: String,default: 'default',},index: {type: Number,default: null,},fieldForm: {type: Object,default: () => { },},
});
const { fieldForm, size } = toRefs(props);// 定义$emit
const $emit = defineEmits(['change']);const { commonChange, isEmptyValue } = Hooks($emit);
</script>

4.Hooks.ts

代码如下(示例):

export default function ($emit: any) {/*** 常规组件change事件*/const commonChange = (item: any, index: any, value: any, data: any) => {$emit('change', item, index, value, data);};/*** 判断是空值*/const isEmptyValue = (value: any) => {return value === null || value == undefined;};return {commonChange,isEmptyValue,};
}

5.Hooks.ts

代码如下(示例):

/*** Created by yxk at 2020/6/1* 单个自定义字段生成校验规则*///类型判断 这些就不贴出来啦
import { isEmpty, isObject, isArray } from '@/utils/types.ts';
export default function () {/*** 唯一性校验* @param data* @returns {Promise<unknown>}* @constructor*/const UniquePromise = (data: any) => {return new Promise((resolve: any) => {resolve(data);});};/*** 生成单个字段的验证规则* @param item 字段信息* @returns {[]}*/const getRules = (item: any) => {const tempList = [];// 验证必填if (item.isNull === 1) {if (item.formType === 'detail_table') {tempList.push({validator: ({ item }: any, value: any, callback: any) => {if (getDetailTableIsEmpty(item.fieldExtendList, value)) {callback(new Error(item.name + '不能为空'));} else {callback();}},item: item,trigger: ['blur', 'change']});} else if (item.formType === 'checkbox' || item.formType === 'dep-select') {tempList.push({validator: ({ item }: any, value: any, callback: any) => {if (!isArray(value) || value.length === 0) {callback(new Error(item.name + '不能为空'));} else {const emptyObj = value.find((valueItem: any) => isEmpty(valueItem));emptyObj === '' ? callback(new Error(item.name + '不能为空')) : callback();}},item: item,trigger: ['blur', 'change']});} else {tempList.push({required: true,message: item.name + '不能为空',trigger: ['blur', 'change']});}}// 验证唯一if (item.isUnique === 1 && UniquePromise) {const validateUnique = (rule: any, value: any, callback: any) => {if (isEmpty(value)) {callback();} else {// 验证唯一UniquePromise({field: item,rule: rule,value: value}).then(() => {callback();}).catch(msg => {callback(new Error(msg || '验证出错'));});}};tempList.push({validator: validateUnique,item: item,trigger:item.formType === 'checkbox' || item.formType === 'select' ?['change', 'blur'] :['blur']});}return tempList;};/*** 获取数值规则*/const getNumberRule = (rule: any, value: any, callback: any) => {const field = rule.item;const arr = String(value).split('.');const len = String(value).replace('.', '').replace('-', '').length;const maxlength = field.formType === 'percent' ? 10 : 15;const min = isEmpty(field.minNumRestrict) ? -Infinity : Number(field.minNumRestrict || -Infinity);const max = isEmpty(field.maxNumRestrict) ? Infinity : Number(field.maxNumRestrict || Infinity);if (len > maxlength) {callback(new Error(`最多支持${maxlength}位数字(包含小数位)`));} else if (isEmpty(field.precisions) && String(value).includes('.')) {// null 不支持小数  0 不限制小数位callback(new Error(`不支持小数`));} else if (arr.length > 1 && arr[1].length > Number(field.precisions)) {callback(new Error(`小数位不能大于${field.precisions}`));} else if (value < min) {callback(new Error(`不能小于${min}`));} else if (value > max) {callback(new Error(`不能大于${max}`));} else {callback();}};/*** 判断明细表格是否是空* @param {*} fieldList* @param {*} valueObj*/const getDetailTableIsEmpty = (fieldList: any, valueObjs: any) => {for (let index = 0; index < valueObjs.length; index++) {const valueObj = valueObjs[index];if (judgeFormValueIsEmpty(fieldList, valueObj)) {return true;}}return false;};/*** 判断对象值是否是空*/const judgeFormValueIsEmpty = (fieldList: any, valueObj: any) => {for (let index = 0; index < fieldList.length; index++) {const field = fieldList[index];const value = valueObj[field.fieldName];if (field.formType === 'location') {if (isObject(value) && (!isEmpty(value.lat) || !isEmpty(value.lng) ||                     !isEmpty(value.address))) {return false;}} else if (!isEmpty(value)) {return false;}}return true;};return {UniquePromise,getRules};
}

6.form表单的使用

<div class="form_container"><Form:field-list="fieldList":field-form="fieldForm" /></div>
const formData = reactive({fieldForm: {},fieldList: [{field: 'name',name: '活动名称',mold: 'Input',formType: 'text',// 检验唯一性isNull:1},{field: 'region',name: '活动区域',mold: 'Select',formType: 'select',setting: [{label: '区域一',value: 0},{label: '区域二',value: 0}]},{field: 'date',name: '活动区域',mold: 'Date',formType: 'datetime',},{field: 'deliver',name: '即时配送',mold: 'Select',formType: 'switch',},{field: 'type',name: '活动性质',mold: 'Select',formType: 'checkbox-group',setting: [{label: '美食/餐厅线上活动',},{label: '地推活动',},{label: '线下主题活动',},{label: '单纯品牌曝光',},]},{field: 'resource',name: '资源',mold: 'Select',formType: 'radio-group',setting: [{label: '线上品牌商赞助',value:0},{label: '线下场地免费',value:1},]},{field: 'desc',name: '活动形式',mold: 'Input',formType: 'textarea',rows:3},]
});

出来的效果就是这样子滴

总结

以上就是form表单的全部代码啦 如果对您有用就浅浅的点个赞吧

基于vue3 element plus form 表单的二次封装相关推荐

  1. element实现form表单动态添加email效果

    前言: vue中使用element实现form表单动态添加email效果 效果: 实现步骤: 实现源代码: <template><div><el-form ref=&qu ...

  2. ExtJs 备忘录(2)—— Form表单(二) [ 控件封装 ]

    前言 本以为可以稳稳当当的工作.安安心心的写文章,结果我做了一件非常疯狂的事情,换新工作一周后辞了--然后去了另外一家公司 - - #,理由就不详说了,总之现在是每天加班到8-9点,虽然如此但是这个团 ...

  3. Element Ui使用技巧——Form表单的校验规则rules详细说明;element的 form 表单rules详细用法

    本文章是在项目开发时遇到问题看到的一片好文, 摘录自[博客园]–[逍遥云天]. 感谢作者 地址 – https://www.cnblogs.com/xyyt/p/13366812.html 在 [逍遥 ...

  4. 例子---PHP与Form表单之二

    大家早上好,很庆幸自己没有被双十一屠害,留了一双手来跟大家一起学习,哈哈,我猜很多小伙伴又要剁手了,还说要吃土,然后就又会出现"剁了骨头连着筋"和"要吃肉要吃肉要吃肉&q ...

  5. 上传多张图片的html表单,element在form表单里上传多张张图片

    1.template里面 title="新增" :visible.sync="Visible" width="30%" > ref=& ...

  6. element中form表单resetFields()方法重置表单无效

    官方文档 // 调用resetFields但没有生效 resetForm() {this.$refs['form'].resetFields(); } 解决: form里需要ref 表单项el-for ...

  7. vue 表单验证正则_vue elementui form表单验证的实现

    最近我们公司将前端框架由easyui 改为 vue+elementui .自学vue两周 就开始了爬坑之路.业余时间给大家分享一下心得,技术新手加上第一次分享(小激动),有什么不足的地方欢迎大家指正, ...

  8. React之Form表单封装

    文章目录 一.form表单封装之树形选择框封装 1. 代码结构 (1)html代码 (2)树形选择框的结构 (3)css (4)转化函数 2. 使用方法 (1)单独使用 (2)和form表单一起使用 ...

  9. element手机验证格式_基于Vue+elementUI实现动态表单的校验功能(根据条件动态切换校验格式)...

    前言 开发过程中遇到了一个需求,根据用户选择的联系方式,动态改变输入框的检验条件,并且整个表单是可以增加的 在线访问:动态表单校验 github(欢迎star): https://github.com ...

最新文章

  1. 一文读懂云计算、边缘计算、移动边缘计算和自动驾驶的前世今生!
  2. Centos下运行gpg --gen-key生成key时出现卡住解决方案笔记
  3. IE9上特定网站不断崩溃的故障
  4. OpenCV加mySQL树莓派_树莓派3B/3B+和4B安装OpenCV教程 (详细教程)
  5. VBS 连接数据库 - 样例
  6. 【期望】乘坐电梯(金牌导航 期望-2)
  7. Java – JDK 8的远景
  8. 基础拾遗------webservice详解
  9. 论文浅尝 - TACL2020 | 改进低资源跨语言实体链接的候选生成问题
  10. python 编码 解码 读写文件
  11. linux查看etl进程,常见ETL工具
  12. 日志分析平台-ELK
  13. sqlite3 语法
  14. 重磅进展,Intel已能够生产量子芯片硅晶圆
  15. python第一周练习 货币转换
  16. 微分方程计算机仿真国内外研究论文,微分方程数值解法毕业论文--开题报告.doc...
  17. 求最短路径算法之SPFA算法
  18. Veeam备份的虚拟机恢复后遇到磁盘问题无法打开虚拟机
  19. php今日头条抓取正文,今日头条文章爬虫采集 - 八爪鱼采集器
  20. 将OpenCV抓拍的图片进行x264编码并保存到文件

热门文章

  1. 12个Unity5中优化VR 应用的技巧
  2. 前端开发面试题—CSS盒子模型
  3. Python tkinter - 第五章 按钮控件(Button)属性
  4. flutter截取字符串_字符串截取的常用方法
  5. Python标准库中的re模块
  6. 【第45题】常用的数学工具类2-三角函数的使用
  7. php中 r,PHP中转义字符 (n r)
  8. microsoftonenote_微软的OneNote是干什么用的?
  9. C# 数据库查询语句1
  10. 下载文件的几种方法: