找回密码
 会员注册
查看: 27|回复: 0

表单数据形式配置化设计

[复制链接]

2万

主题

0

回帖

6万

积分

超级版主

积分
64454
发表于 2024-10-10 20:29:09 | 显示全部楼层 |阅读模式
这是第151篇不掺水的,想要了解更多,请戳下方卡片关注我们吧~表单数据形式配置化设计https://www.zoo.team/article/form-data前言在日常的中后台系统开发中,表单是和我们打交道非常多的名词。但是在一般的表单实现中、我们会做着很多重复的工作,不停在写 FormItem...,以及为组件加上“请输入/请选择”等无脑的 placeholder 文本和“请输入 xx/ 请选择 xx” 等必填提示。其次表单一般都存在编辑页和页,而为了代码更好的维护性通常会将编辑和用一套代码实现。此时我们的代码里就会出现 isEdit ?表单组件 :纯文本”这样无脑且重复率高的代码。秉承着更少代码更多产出的原则,我设计了一套配置化逻辑来提升这一开发体验。一般实现//一般实现importReactfrom'react';import{Form,Input,Select}from'antd';constDemo=(props)=>{const{form:{getFieldDecorator},obj={},isEdit}=props;return({isEditobj.name||'-':getFieldDecorator('name',{initialValuebj.name,})()}{isEditobj.sex||'-':getFieldDecorator('sex',{initialValuebj.sex,rules:[{required:true,message:'请选择性别'}],})(男女)}{isEditobj.phone||'-':getFieldDecorator('phone',{initialValuebj.phone,rules:[{required:true,message:'请输入手机号'}],})()})}配置化的实现//配置化的实现importReactfrom'react';import{renderDataForm}from'src/util/renderDataForm';constDemo=(props)=>{const{form,obj={},isEdit}=props;constconf=[{label:'姓名',//表单的labelfield:'name',//表单字段名initialValuebj.name,//表单默认值required:false,//是否必填、默认必填},{label:'性别',field:'sex',initialValuebj.sex,formItemType:'Select',//表单类型默认Inputoptions:[{value:'male',label:'男'},{value:'female',label:'女'}],//下拉选项},{label:'手机号',field:'phone',initialValuebj.phone,}];constdataForm=isEdit'form':'text';//传入form,表单配置,想要的数据形式returnrenderDataForm(form,conf,dataForm));}实现思路如上图所示,无论是在页中显示文本亦或是编辑页中的表单组件包裹的数据,其实本身所对应的都是同一个数据,只是展示形式不一样而已。在这里我们暂时将数据的形式定为表单组件形式与文本形式。其实在实际的使用中,由于数据的收集形式不同,会出现第三种数据形式。它就是表单文本形式,一种以文本展示但数据可被表单自动收集的形式,我把它定义为 FormText(如下所示)。至此,针对实现数据与编辑形式的方案有了这样两种,表单与文本组合或表单与表单文本组合的实现。本次我选择表单与文本组合的方案。/***用于Form表单内部受控展示文本*/exportdefaultclassFormTextextendsComponent{render(){const{value,formatMethod=a=>a,defaultText='-',...resetProps}=this.props;return{formatMethod(value)||defaultText};}}//使用{getFieldDecorator('name',{initialValue:'egg',})()}具体实现1、形式选择(表单组件 or 文本)constrenderDataForm=(form,conf={},dataForm='form')=>{//customRenderText自定义文本形式const{customRenderText}=conf;return({dataForm==='form'renderFormItem(form,conf):customRenderTextcustomRenderText(conf):renderText(conf)});};2、表单组件选择exportconstrenderFormItem=(form,rest)=>{const{getFieldDecorator}=form;const{label='',field='',formItemType='input',initialValue,required=true,rules=[],...itemRest}=rest;return(getFieldDecorator(field,{initialValue,rules:[//必填提示{required,message:renderMessage(formItemType,label)},...rules,],...(formItemType==='upload'{//Upload组件的通用配置getValueFromEvente)=>{if(Array.isArray(e)){returne;}returne&e.fileList;},valuePropName:'fileList'}:{}),})(renderItem(formItemType,itemRest)));};//选择表单组件constrenderItem=(formItemType,itemRest)=>{const{options=[],CustomFormItem}=itemRest;constobj={Input,TextArea,InputNumber,Upload,Select,RadioGroup,CheckboxGroup,DatePicker};//自定义的表单组件if(formItemType==='CustomFormItem'){return;}//不存在对应组件时返回默认的Input组件if(!obj[formItemType]){return;}constComp=obj[formItemType];//双标签组件处理if(['Select','Upload'].includes(formItemType)){returnformItemType==='Upload'(上传){options.map(el=>({el.label||el.name}))});}//单标签组件return;};//获取组件属性constgetDefaultCompProps=(conf={})=>{const{formItemType}=conf;constprops={};props.placeholder=renderMessage(formItemType);if(formItemType==='InputNumber'){//zeroOmit小数点后多余的零是否省略,limitDecimal限制最长的小数位数const{zeroOmit=true,limitDecimal=6}=conf;constlimitDecimalsF=(value)=>{constreg=newRegExp(`^(-)*(\\d+)\\.(\\d{${limitDecimal}}).* );return`${value}`.replace(reg,'$1$2.$3');};if(zeroOmit){props.formatter=limitDecimalsF;props.parse=limitDecimalsF;}}if(formItemType==='Input'){props.maxLength=100;//输入框的默认最大输入字符长度}if(formItemType==='TextArea'){props.maxLength=500;//文本框的默认最大输入字符长度}returnprops;};3、映射文本exportconstrenderText=(rest)=>{const{formItemType='Input',initialValue,selectOptions=[],selectMode='',options=[]}=rest;switch(formItemType){case'RadioGroup':return(options.find(item=>item.value===initialValue)||{}).label||'-';case'DatePick':const{format='YYYY-MM-DDHH:mm:ss'}=rest;//日期组件组件值格式化为对应的文本returninitialValue!==undefinedmoment(initialValue).format(format):'-';//...codedefault:returnbizStringFormat(initialValue);//无值时默认‘-’}}4、通用校验规则整理exportconstpostCode=/^[0-9]{6}$/;exportconstphone=/^1\d{10}$/;//...其他正则//formrulesexportconstpostCodeRule={pattern:postCode,message:'请输入6位数字',};exportconstphoneRule={pattern:phone,message:'请输入11位号码',};//...其他表单校验规则使用示例constDemo=(props)=>{const{form}=props;//数据constobj={email:'123@egg.com',addr:'派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星派大星',sort:'up',birthday:'1999-01-23',sex:'male',file:[{fileId:'123',name:'信用承诺书',size:1024}],};//因为数据的形式默认为表单,所以dataForm:'form'可不配置constformConf=[{label:'邮箱',field:'email',initialValuebj.email,rules:[emailRule],//emailRule为邮箱校验规则},{label:'地址',field:'addr',initialValuebj.addr,formItemType:'TextArea',},{label:'排序',field:'sort',initialValuebj.sort,formItemType:'Select',options:[{value:'up',label:'升序'},{value:'down',label:'降序'}],},{label:'生日',field:'birthday',initialValuebj.birthday,formItemType:'DatePicker',format:'YYYY-MM-DD',//日期组件的格式配置字段},{label:'性别',field:'sex',initialValue:obj.sex,formItemType:'RadioGroup',options:[{value:'male',label:'男'},{value:'female',label:'女'}],},{label:'信用承诺书',field:'file',initialValue:obj.file,formItemType:'Upload',}];constdataForm=isEdit'form':'text';//将配置遍历传入renderDataForm//当然你也可以封装成组建,直接向组建传入form、formConf,减少遍历的重复书写和整洁returnformConf.map(item=>renderDataForm(form,item,dataForm));最终呈现如下:编辑触发校验总结虽然,在目前的前端领域,关于页面配置、可视化等更加复杂的能力,已有更丰富和更全面的实现。比如我们前端团队的无相应用早已实现整个表单页的配置化能力。而本文展示的表单块的代码配置化能力接入较为轻量、内容上更容易理解。看完两件事如果你觉得这篇内容对你挺有启发,我想邀请你帮我两件小事1.点个「在看」,让更多人也能看到这篇内容(点了「在看」,bug -1 )2.关注公众号「政采云前端团队」,持续为你推送精选好文招贤纳士政采云前端团队(ZooTeam),一个年轻富有激情和创造力的前端团队,隶属于政采云产品研发部,Base 在风景如画的杭州。团队现有 60 余个前端小伙伴,平均年龄 27 岁,近 3 成是全栈工程师,妥妥的青年风暴团。成员构成既有来自于阿里、网易的“老”兵,也有浙大、中科大、杭电等校的应届新人。团队在日常的业务对接之外,还在物料体系、工程平台、搭建平台、性能体验、云端应用、数据分析及可视化等方向进行技术探索和实战,推动并落地了一系列的内部技术产品,持续探索前端技术体系的新边界。如果你想改变一直被事折腾,希望开始能折腾事;如果你想改变一直被告诫需要多些想法,却无从破局;如果你想改变你有能力去做成那个结果,却不需要你;如果你想改变你想做成的事需要一个团队去支撑,但没你带人的位置;如果你想改变既定的节奏,将会是“5 年工作时间 3 年工作经验”;如果你想改变本来悟性不错,但总是有那一层窗户纸的模糊… 如果你相信相信的力量,相信平凡人能成就非凡事,相信能遇到更好的自己。如果你希望参与到随着业务腾飞的过程,亲手推动一个有着深入的业务理解、完善的技术体系、技术创造价值、影响力外溢的前端团队的成长历程,我觉得我们该聊聊。任何时间,等着你写点什么,发给 ZooTeam@cai-inc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2024-12-27 14:05 , Processed in 0.705731 second(s), 26 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表