前端配置化表单组件设计方法 | 京东云技术团队

news/2024/11/27 2:10:35/

一、背景

前端开发中涉及表单的页面非常多,看似功能简单,开发快速,实则占去了很大一部分时间。当某个表单包含元素过多时还会导致html代码过多,vue文件过大。从而不容易查找、修改和维护。为了提高开发效率及降低维护成本,下面介绍表单配置化组件的封装原理与封装方法。

二、技术方案

如上图所示,封装表单配置化组件的关键点有三个一是如何解决表单元素排布的行列问题,二是表单数据的绑定问题,三是表单元素的参数配置校验等问题。下面分别介绍这三个问题的解决方法。

•配置化表单组件的入参及说明

参数说明类型可选值默认值
labelWidth表单元素label所占宽度String——150px
columnList表单元素所组成的配置,是一个数组Array——[]
formData表单元素值的集合Object——{}
columnSpan表单排布分栏Number——24
size表单元素尺寸Stringmedium / small / minimedium

•计算配置化表单的行数,本表单通过基础的24分栏计算表单最终的行数和列数,通过下面方法最终得到一个关于行列的二维数组

newColumnList() {const newColumnList= []const row = Math.floor(24 / this.columnSpan)let newColumnItem = []for(let i=0; i< this.columnList.length; i++) {newColumnItem.push(this.columnList[i])if(newColumnItem.length === row || i === this.columnList.length-1) {newColumnList.push(newColumnItem)newColumnItem = []}}return newColumnList
}

•通过上面得到的二维数组进行循环渲染,首先循环渲染行,其次循环渲染列。本方案采用element中的表单,当然也可以用其他组件库或者原生表单进行渲染,其原理通用。最终将会根据参数column.type决定加载哪一个具体的表单元素。

<el-form ref="form" :model="formData" :label-width="labelWidth" :size="size"><el-row :gutter="20" v-for="(element,index) in newColumnList" :key="index+'formRow'"><template v-for="(item, index) in element" ><column:key="index + 'formView'":columnSpan="columnSpan":column="item":formData="formData"/></template></el-row>
</el-form>

•column组件最终根据type加载具体的表单元素。下面展示column组件的入参及其说明,通过component加载不同的表单元素

参数说明类型可选值默认值
column表单元素的具体配置Object——{}
formData表单元素值的集合Object——{}
columnSpan表单排布分栏Number——24
<el-col :span="columnSpan"><component:is="column.type + 'View'":column="column":formData="formData"v-model="formData[column.name]":columnSpan="columnSpan"/></el-col>

•这里主要以select表单元素为例进行说明,表单元素的双向绑定、校验以及值更新等问题

参数说明类型可选值默认值
column表单元素的具体配置Object——{}
value表单元素值Number/String/Array————

•column参数

参数说明类型可选值默认值
placeholder空值说明String————
required是否必填Boolean————
rules校验规则Array————
title表单元素labelString————
name表单元素值名称String————
multiple是否多选Boolean————
filterable是否过滤Boolean————
disabled是否禁用Boolean————
dictionary下拉选项枚举Array————
changeFunction值改变时的回调函数Function————
<el-form-item :label="column.title + ':'" :prop="column.name" :rules="rules"><el-selectv-model="val"clearable:multiple="column.multiple":filterable="column.filterable":placeholder="'请选择' + column.title":disabled="column.disabled"style="width: 100%"@change="onChange"@clear="onClear"><el-option v-for="item in column.dictionary" :key="item.code" :label="item.name" :value="item.code"></el-option></el-select>
</el-form-item>
rules:  [{required: this.column.required,message: this.column.placeholder placeholder ? this.column.placeholder : `请输入${this.column.title}`,trigger: 'change'},...this.column.rules]
onChange(){this.$emit('input',this.val)if(this.column && this.column.changeFunction){this.column.changeFunction(this.val)}
},
onClear(){this.onChange()
}

三、项目实践

•配置化表单为bs-form,在页面中引入bs-form表单组件

<bs-form ref="formDemo":columnList="columnList":formData="formData":columnSpan="columnSpan"labelWidth="120px">
</bs-form>
<el-row style="text-align: center;"><el-button type="primary"@click="onSave">保存</el-button><el-button @click="onCancel">取消</el-button>
</el-row>

•formData参数

formData: {name: '',yearIncome: '', // 业务类型goodsCategoryId: '', // 托寄物品类idprojectManagerErp: '', // 项目经理erpprojectName: '', // 项目名称projectStage: '', // 项目阶段编码projectStandardName: '', // 标准名称projectYear: 2023, // 年份startRegionId: '', // 始发区域idstartBattleId: '', // 始发战区idaddress: [], // 省市category: null, //图文类型range: [] //发布范围}

•分栏参数

columnSpan: 6

•表单配置参数

columnList(){const self = thisreturn [{type: 'text',name: 'name',title: '项目名称',required: true,maxlength: 20,showwordlimit: true,placeholder: '请输入'},{name: 'category',type: 'radio',dictionary: [{code: 1,name: '类型一'},{code: 2,name: '类型二'}],title: '图文类型',required: true},{name: 'range',type: 'checkbox',title: '发布范围',dictionary: [{code: 1,name: '范围一'},{code: 2,name: '范围二'}],required: true},{type: 'text',  // 字段类型文本框name: 'yearIncome',  //与后台对接字段title: '年均收入',  // 前端展示字段required: true, // 必填项设置maxlength: 50,  // 字符串长度限制showwordlimit: true, // 是否显示字符串长度placeholder: '请输入', // 占位文本提示rules: [{ pattern: /(^[1-9]([0-9]+)?(.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9].[0-9]([0-9])?$)/, message: '请输入数字最多两位小数' }],},{type: 'select',name: 'goodsCategoryId',title: '托寄物品类',required: true,filterable: true,placeholder: '请选择',dictionary: [{name: '苹果',code: '1'},{name: '手机',code: '2'},{name: '测试',code: '3'},{name: '樱桃',code: '7'},{name: '荸荠',code: '9'}]},{type: 'select',name: 'startRegionId',title: '区域',required: true,placeholder: '请选择',dictionary: [{name: '销售-华北区域',code: '1'},{name: '销售-华东区域',code: '2'},{name: '销售-华南区域',code: '3'},{name: '销售-西南区域',code: '4'},{name: '销售-华中区域',code: '5'},{name: '销售-东北区域',code: '6'}],// 点击下来触发切换联动的事件,为一个函数changeFunction: function (val) {}}, {type: 'select',name: 'startBattleId',title: '战区',required: true,placeholder: '请选择',dictionary: this.battleByRegionList}, {type: 'select',name: 'projectStage',title: '项目阶段',required: true,placeholder: '请选择',dictionary: [{name: '项目发起阶段',code: '10'},{name: '项目调研阶段',code: '20'},{name: '可行性分析阶段',code: '30'},{name: '立项阶段',code: '40'}]}, {type: 'text',name: 'projectStandardName',title: '标准名称',required: true,placeholder: '请输入',append: '.com',  // 文本框后置内容}, {type: 'text',name: 'projectManagerErp',title: '项目经理',required: true,placeholder: '请输入'},{type: 'cascader',  // 字段类型下拉框name: 'address',   //与后台对接字段title: '省市区',  // 前端展示字段required: true, // 必填项设置placeholder:'请选择',  // 占位文本提示dictionary: [{value: 'shanxi',label: '陕西省',children: [{value: 'xian',label: '西安市',children: [{value: 'yanta',label: '雁塔区'}, {value: 'beilin',label: '碑林区'}, {value: 'xincheng',label: '新城区'}, {value: 'weiyang',label: '未央区'}]}]}],// 点击下来触发切换联动的事件,为一个函数changeFunction: function(){}},{type: 'static',name: 'projectYear',title: '年份'}]
}

•表单保存

// 保存
async onSave() {const valid = await this.$refs.formDemo.onValidate()if(valid) {this.$message.success('校验通过')}else {this.$message.error('校验失败')}
}

四、成果展示

作者:京东物流 田雷雷


http://www.ppmy.cn/news/61888.html

相关文章

测牛学堂:2023软件测试入门学习指南(测试理论之缺陷相关内容详解)

缺陷是什么&#xff1f; 缺陷&#xff0c;也就是我们口中的bug。在IEEE的定义是&#xff1a;计算机软件或程序中存在某种破坏正常运行能力的问题&#xff0c;错误&#xff0c;隐藏的功能错误。 开发过程或维护过程中引入的错误&#xff0c;或者 在使用过程中&#xff0c;软件…

第六章 Iptables与Firewalld防火墙

文章目录 第六章 Iptables与Firewalld防火墙一、Iptables1、策略与规则链&#xff08;1&#xff09;、防火墙策略规则的设置&#xff08;2&#xff09;、数据包处理位置 2、基本的命令参数&#xff08;1&#xff09;、iptables中常用的参数以及作用&#xff08;2&#xff09;、…

西安研究所分享

1. 航空工业和中国航发 • 第603研究所&#xff08;第一飞机设计研究院&#xff0c;一飞院&#xff09; 位于西安阎良区&#xff0c;距离主城50公里。待遇杠杠的&#xff0c;门槛很高 • 第618研究所&#xff08;中国飞行自动控制研究所&#xff09; 核心部门是控制、导航和电…

2023年深圳CPDA数据分析师认证到这里就对了哦

CPDA数据分析师认证是大数据方面的认证&#xff0c;助力数据分析人员打下扎实的数据分析基础知识功底&#xff0c;为入门数据分析保驾护航。 帮助数据分析人员掌握系统化的数据分析思维和方法论&#xff0c;提升工作效率和决策能力&#xff0c;遇到问题能够举一反三&#xff0c…

go-zero

目录 引入开发派系标准库/自研派系——不要让框架束缚开发web框架派系——gingrpc大一统框架 go-zerogo-zero快速实现一个微服务user serviceorder api server启动 goctl安装生成的api网关目录生成的pb目录api语法syntaximport语法块infotypeservice注释 命令大全 引入 该图片来…

开放原子训练营(第三季)inBuilder低代码开发实验室---报销单录入系统

作为一名低代码初学者&#xff0c;我使用inBuilder系统设计了一款报销单录入系统&#xff0c;实现了报销单录入与显示报销单列表的功能&#xff08;如图1与图2所示&#xff09;&#xff0c;并获得了很多开发心得。从inBuilder系统的优点、缺点以及开发过程三方面出发&#xff0…

Three.js--》模型材质与纹理的使用

目录 初识材质与纹理 修改模型材质颜色 模型添加纹理 纹理常用属性使用 纹理显示算法 设置粗糙度 纹理加载进度情况 设置环境贴图 初识材质与纹理 three.js中的材质就是几何体表面的材料。所有材质均继承自Material。ThreeJS的材质分为&#xff1a;基础材质、深度材质…

深入理解 Linux 内核(二)

系列文章目录 Linux 内核设计与实现 深入理解 Linux 内核&#xff08;一&#xff09; 深入理解 Linux 内核&#xff08;二&#xff09; Linux 设备驱动程序 Linux设备驱动开发详解 文章目录 系列文章目录六、定时测量1、时钟和定时器电路2、Linux 计时体系结构&#xff08;1&am…