Ant Design4中Form.List和shouldUpdate一起使用的坑

背景

        在antd3.x版本中,如果要实现一组表单增加删除的功能,需要Array.map()加上state状态来控制,代码比较复杂,而且非常不优雅。

        其次在antd3.x中,表单中任何一个表单项的内容更新都会触发页面重新渲染,这在一个巨型表单页面上简直是灾难。(但是这对于表单联动却是非常方便的,只需要在需要联动的表单前加上判断语句即可)

        因此。antd4相对于antd3对表单进行了一些优化,其中就增加了Form.List这个API和shouldUpdate方法。

        其中Form.List为字段提供数组化管理,可用于动态增加删除移动表单项。

        Form.Item上的shouldUpdate方法用来自定义字段的更新逻辑。

        但是其中有一些坑真让人头大

坑1:同时联动多个表单,样式问题

        首先,antd3中实现联动的方法在4版本中并不好使,原因就是在antd4中表单内容的更新并不会触发页面的渲染。在antd4中我们有两种方法可以用来控制表单联动,那就是dependencies方法和shouldUpdate方法。

        对比了一下官方文档的两种方法,个人感觉

        dependencies适用于针对依赖字段重新触发校验逻辑的场景

        shouldUpdate适应于针对依赖字段对某一区域进行渲染的场景

        所以我们就采用shouldUpdate方法来处理联动。但是当我们实际开发过程中,如果我们是控制一个表单项的联动还好,如果同时控制多个表单项联动,有两种方案

// 方案1:<Form.Item noStyle shouldUpdate={(prevValues, curValues) => { return prevValues.type !== curValues.type; }} >{() => {return <Form.Item label="名字" name={'name'} ><Input placeholder='请输入' /></Form.Item>}}
</Form.Item>
<Form.Item noStyle shouldUpdate={(prevValues, curValues) => { return prevValues.type !== curValues.type; }} >{() => {return <Form.Item label="年龄" name={'age'} ><Input placeholder='请输入' /></Form.Item>}}
</Form.Item>// 方案2:
<Form.Item noStyle shouldUpdate={(prevValues, curValues) => { return prevValues.type !== curValues.type; }} >{() => {return <><Form.Item label="名字" name={'name'} ><Input placeholder='请输入' /></Form.Item><Form.Item label="年龄" name={'age'} ><Input placeholder='请输入' /></Form.Item></>}}
</Form.Item>

        如果采用第一种方案,代码会比较冗余,而且如果表单有多处联动,不太容易区分哪个是联动哪个的,因为是平铺下来的嘛

        如果采用第二种方案,会很直观的看出来,某处联动会联动哪几个表单。但是这里有个坑,即使我们设置了noStyle和空标签,被关联的多个表单还是会被一个div包裹起来。这会带来的后果就是,假设一行只有一个固定字段,其他都是被关联的字段,当被关联字段超过了一行能容纳的个数的话会整体换行,导致第一行只留下一个字段,样式布局则会很奇怪。如图

        针对这个问题,目前还没想到完美的解决方案,如果有比较好想法的小伙伴,欢迎分享你的想法哟。

坑2:不管是通过dependencies方法还是shouldUpdate方法。当我们通过联动,隐藏某几个表单项后,已收集到form中的数据并不会删除。

<Form.Item noStyle shouldUpdate={(prevValues, curValues) => { return prevValues.type !== curValues.type }} >{({ getFieldValue }) => {const type = getFieldValue('type');if (type === '1') {return <><Form.Item label="名字" name={'name'} ><Input placeholder='请输入' /></Form.Item><Form.Item label="年龄" name={'age'} ><Input placeholder='请输入' /></Form.Item></>} else if (type === '2') {return <Form.Item label="性别" name={'sex'} ><Input placeholder='请输入' /></Form.Item>}return null}}
</Form.Item>

        看下面代码,这段代码是当表单中type类型为1时 ,展示名字和年龄字段,当type为2时,展示性别字段

        如果我们将type切换成1再切换成2, 表单中会存在名字和年龄,但是在页面上并不存在这两个表单项。

        这并不会影响什么,但是个人感觉很不干爽,如果表单变大变复杂,提交表单时也会提交过去一些可能并不需要的字段。因此我们最好删除掉不需要的字段。

这个问题,能够直接想到两种方案。

        方案1:在最后提交表单的时候做一下特殊处理。将多余的字段删除后再提交。但是如果在提交前再次回显表单项的时候,还是会回显之前残留的数据,时机太晚。

        方案2:在表单联动隐藏的时候,对字段进行重置。考虑使用resetFields,但是经过实践并不好用。可以采用setFieldsValue或setFields对字段进行重置,在如下位置添加相应重置逻辑

<Form.Item noStyle shouldUpdate={(prevValues, curValues) => { return prevValues.type !== curValues.type }} >{({ getFieldValue }) => {const type = getFieldValue('type');if (type === '1') {{/** 重置表单内容,并初始化名字和年龄 */ }return <><Form.Item label="名字" name={'name'} ><Input placeholder='请输入' /></Form.Item><Form.Item label="年龄" name={'age'} ><Input placeholder='请输入' /></Form.Item></>} else if (type === '2') {{/** 重置表单内容,并初始化性别 */ }return <Form.Item label="性别" name={'sex'} ><Input placeholder='请输入' /></Form.Item>}return null}}
</Form.Item>

        如果表单是固定的话,单独这样写是没啥问题的。

        如果我们使用formList来为字段提供数组化管理,动态增减表单项的话。上述方法则会出现一个新的坑。

坑3: formList重新渲染的问题

        在上述代码的基础上,如果我们通过formList来包裹的话。正常情况是相互并不干扰的,但是,如果我们使用formList的add或remove方法,则会触发formList的重新渲染,带来的后果则是,重置每一组的表单内容。

        解决办法是将重置逻辑写到type表单项的onchange方法中即可

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/8564.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot整合minio服务(超详细)

一、使用docker部署minio 1、拉取镜像 docker pull minio/minio 2、创建目录 mkdir -p /home/minio/config mkdir -p /home/minio/data 3、创建Minio容器并运行 docker run -p 9000:9000 -p 9090:9090 \--nethost \--name minio \-d --restartalways \-e "MINIO_ACC…

nginx

Nginx yum安装 配置Nginx的yum源 [nginx] namenginx repo baseurlhttp://nginx.org/packages/centos/$releasever/$basearch/ gpgcheck0 enabled1安装以及重启&#xff0c;检查 yum -y install nginx 默认安装最新版本 启动 关闭 重启 加载 systemctl start/stop/restar…

《安全软件开发框架(SSDF) 1.1:降低软件漏洞风险的建议》解读(三)

安全软件开发框架SSDF是由美国国家标准与技术研究院发布的关于安全软件开发的一组实践&#xff0c;帮助开发组织减少发布的软件中的漏洞数量&#xff0c;减少利用未检测到或未解决的漏洞的潜在影响&#xff0c;从根本上解决漏洞防止再次发生。本文根据《Secure Software Develo…

基于 Opencv python实现批量图片去黑边—裁剪—压缩软件

简介 批量处理图片文件&#xff0c;批量提取GIF图片中的每一帧&#xff0c;具有范围裁剪、自动去除黑/白边、调整大小、压缩体积等功能。 先看一些软件的界面&#xff0c;是基于Tkinter写的GUI 裁剪等功能基于Opencv 下载 我添加了处理GIF的github&#xff1a; 原作者的gith…

深度学习基础

1 机器学习、深度学习、人工智能 1.1 机器学习 机器学习是一门专门研究计算机怎样模拟或实现人类的学习行为&#xff0c;以获取新的知识或技能&#xff0c;重新组织已有的知识结构使之不断改善自身性能的学科。 基本步骤&#xff1a;获取数据、数据预处理、特征提取、特征选择…

C# 元组

文章目录 C# 元组Tuple 类ValueTuple 类ValueTuple 与 Tuple的区别System.ValueTuple 类型的值是可变的System.Tuple 类型的值是不可变的System.ValueTuple 类型的数据成员是字段 System.ValueTuple 与匿名类在使用Linq查询时&#xff0c;如何权衡使用元组还是匿名类权衡主要区…

奇点云DataSimba R4.9 LTS发布:稳定性加固,架构升级,142项功能上新

不久前&#xff0c;奇点云的数据云全系产品如期发布新一季商业化版本更新&#xff1a; 数据云平台DataSimba&#xff1a;R4.9 LTS版发布&#xff0c;稳定性全面加固&#xff0c;功能上新&#xff1b;自R4系列起架构升级&#xff0c;封装底层复杂性&#xff0c;支撑上层快速构建…

CSS圆角进化论

CSS圆角发展过程 大致经历了3个阶段&#xff0c;包括&#xff1a; 背景图片实现圆角CSS2.0标签模拟圆角CSS3.0圆角属性&#xff08;border-radius属性)实现圆角 ☛背景图片实现圆角&#xff1a;使用背景图片实现圆角的方式很多&#xff0c;实现的方式和圆角的切图方式关系密…

Nacos服务注册成功,RestTemplate调用服务提供者时空指针异常(已解决)

发现问题并进行记录 目录 项目场景&#xff1a;问题描述原因分析解决 项目场景&#xff1a; RestTemplate也可以做服务调用(进行测试) 目的:解决该问题,不考虑其他远程调用方式(Fegin,Dubbo) 项目Pom文件 Spring Boot ----2.6.3 Spring Cloud------2021.0.1 Spring Cloud Al…

vue动态修改浏览器标题和logo

问题描述 需要将一个系统&#xff0c;更改一下标题、logo&#xff0c;然后部署成另一个系统&#xff0c;由于不想单独拉出一套代码&#xff08;单独拉出来后维护成本增加&#xff09;&#xff0c;所以想要动态改变系统标题和图标 解决方案 将项目制造一个入口可以修改项目的…

Unity | HDRP高清渲染管线学习笔记:Rendering Debugger窗口

HDRP给我们提供了一套完整的可视化Debug工具&#xff0c;集成在Rendering Debugger窗口。通过顶部菜单Window→Analysis→Rendering Debugger可以打开窗口。Rendering Debugger窗口不仅仅可以在编辑模式下使用&#xff0c;也可以在真机上运行时使用。&#xff08;要在真机上运行…