React hook+AntD pro实现Form表单的二次封装
React hook+AntD pro实现Form表单的二次封装
- 封装Form表单
- 1、在src/types下新建 antd/form/index.ts,进行Form表的配置、数据等类型的限制
- 2、在 根目录/components 下新建 BaseForm/index.tsx文件
- 3、在BaseForm/createFormIpt.tsx中,抽取对不同类型的表单元素渲染
- 4、在src/pages/PublishArticle/下,新建驱动表单的数据文件data.ts
- 5、在src/pages/PublishArticle/下,新建使用二次封装的Form组件的父组件index.ts
封装Form表单
关键hooks API: useImperativeHandle、useRef,高阶组件: forwardRef,
1、在src/types下新建 antd/form/index.ts,进行Form表的配置、数据等类型的限制
import React, { ReactNode } from 'react';
import { IButton } from '@/types/antd/button';
// @ts-ignore
import { FilterFunc, GetFieldsValueConfig } from 'rc-field-form/es/interface';type RadioGroupOption = {buttonStyle?: 'outline' | 'solid';name?: string;options?: any[];optionType?: 'default' | 'button',size?: 'large' | 'middle' | 'small',
}type SelectOptions = {mode?: 'multiple' | 'tags';options?: any[];
}
export type FormOptions = {// 表单名称,会作为表单字段 id 前缀使用name: string;labelCol?: number;wrapperCol?: number;autoComplete?: string;// label 是否显示冒号colon?: boolean;// label 标签的文本对齐方式labelAlign?: 'right' | 'left';// 表单布局layout?: 'horizontal' | 'vertical' | 'inline';// 设置字段组件的尺寸(仅限 antd 组件)size?: 'small' | 'middle' | 'large';// initialValues?: {[index: string]: any}
}export type FormItemOptions = {// 是否显示 label 后面的冒号colon?: boolean;// label 标签的文本label?: ReactNode | string;placeholder?: string;name: string; // use is key// 标签文本对齐方式labelAlign?: 'left' | 'right';labelCol?: number;wrapperCol?: number;noStyle?: boolean;required?: boolean;// 设置防抖,延迟毫秒数后进行校验validateDebounce?: number;// 设置字段校验的时机 : onChangevalidateTrigger?: string | string[];// input 图标prefix?: React.ReactElement;formItemType: string;rules?: {[index: string]: string | boolean}[];formButtons?: IButton[],rows?: number;allowClear?: boolean;selectOptions?: SelectOptions;radioOptions?: RadioGroupOption;
}export interface IFormProps {formOptions: FormOptions;formValue: {[index: string]: any};formItemOptions: FormItemOptions[];emitSubmit?: (formData: any) => void;
}// SystemForm 组件暴露的数据结构
export interface IFormCompExportData {getFieldsValue: (() => any) & ((nameList: (true | any[]), filterFunc?: (FilterFunc | undefined)) => any) & ((config: GetFieldsValueConfig) => any)
}
2、在 根目录/components 下新建 BaseForm/index.tsx文件
子组件:Form的二次封装组件
import React, { forwardRef, useImperativeHandle } from 'react';
import { IFormCompExportData, IFormProps } from '@/types/antd/form';
import createFormIpt from './createFormIpt';
import { Form } from 'antd';const SystemForm = (props: IFormProps, ref: React.Ref<any>) => {const {formOptions,formItemOptions,emitSubmit,formValue,} = props;const [form] = Form.useForm();// useImperativeHandle: 细化ref暴露的实例粒度useImperativeHandle(ref, (): IFormCompExportData=>({// 这里可以暴露SystemForm组件的所有内容 变量、方法、元素实例// 避免暴露出 完整的Form表单实例form 这里选择暴露获取字段value方法getFieldsValue的引用getFieldsValue: form.getFieldsValue}), [])const onFinish = (values: any) => {emitSubmit && emitSubmit(values);};return (<Formform={form}name={formOptions.name}labelCol={{ span: formOptions.labelCol }}wrapperCol={{ span: formOptions.wrapperCol }}initialValues={formValue}autoComplete={formOptions.autoComplete}size={formOptions.size}onFinish={onFinish}>{formItemOptions.map(item => {return (<Form.Itemkey={item.name}label={item.label}name={item.name}rules={item.rules}>{/*<CreateFormIpt formItem={item} />*/}{createFormIpt(item)}</Form.Item>);})}</Form>);
};// 因为有forwardRef包裹,所以SystemForm组件才可以使用第二个参数ref
export default forwardRef(SystemForm);
3、在BaseForm/createFormIpt.tsx中,抽取对不同类型的表单元素渲染
import { FormItemOptions } from '@/types/antd/form';
import React from 'react';
import { Button, Input, Select, Radio } from 'antd';const { TextArea} = Input;const createFormIpt = (formItem: FormItemOptions) => {if(formItem.name === 'password') {return (<Input type="password" prefix={formItem.prefix} placeholder={formItem.placeholder}/>)}const iptRenderMapByFormItemType: {[index: string]: React.JSX.Element} = {'input': <Input prefix={formItem.prefix} placeholder={formItem.placeholder} allowClear={formItem.allowClear}/>,'textarea':<TextArea rows={formItem.rows} placeholder={formItem.placeholder} allowClear={formItem.allowClear} />,'radio': <Radio.Group options={formItem.radioOptions?.options}/>,'select': <Selectplaceholder={formItem.placeholder}mode={formItem.selectOptions?.mode}allowClear={formItem.allowClear}options={formItem.selectOptions?.options}/>,'button': <>{formItem.formButtons?.map(itemBtn=>(<Buttonkey={itemBtn.key}type={itemBtn.buttonType}loading={itemBtn.btnLoadingStatus}block={itemBtn.block}htmlType={itemBtn.htmlType}>{itemBtn.btnDesc}</Button>))}</>,}return iptRenderMapByFormItemType[formItem.formItemType]
}export default createFormIpt;
4、在src/pages/PublishArticle/下,新建驱动表单的数据文件data.ts
import { FormOptions, FormItemOptions } from '@/types/antd/form';export const publishArticleFormValue = {'title': '11s','content': '','summary': '','categoryId': '','tags': [],'isComment': '0','isTop': '0','thumbnail': '',
}// 文章表单
export const publishArticleFormOptions: FormOptions = {name: 'publishArticle',autoComplete: 'off',size: 'large',labelCol: 4,wrapperCol: 20,
}export const publishArticleFormData: FormItemOptions[] = [{label: '文章标题',name: 'title',placeholder: '请输入文章标题',formItemType: 'input',allowClear: true,},{label: '文章摘要',name: 'summary',placeholder: '请输入文章摘要',formItemType: 'textarea',allowClear: true,},{label: '分类',name: 'categoryId',placeholder: '请选择',formItemType: 'select',selectOptions: {},allowClear: true,},{label: '标签',name: 'tags',placeholder: '请选择',formItemType: 'select',selectOptions: {mode: 'multiple'},allowClear: true,},{label: '允许评论',name: 'isComment',formItemType: 'radio',radioOptions: {options: [{ label: '正常', value: '1' },{ label: '停用', value: '0' }]}},{label: '是否置顶',name: 'isTop',formItemType: 'radio',radioOptions: {options: [{ label: '是', value: '1' },{ label: '否', value: '0' }]}},
]
5、在src/pages/PublishArticle/下,新建使用二次封装的Form组件的父组件index.ts
import React, { useRef, useState } from 'react';
import { PageContainer } from '@ant-design/pro-components';
import {publishArticleFormData,publishArticleFormOptions,publishArticleFormValue,
} from '@/pages/PublishArticle/data';
import { IFormCompExportData } from '@/types/antd/form';const PublishArticle: React.FC = () => {// useRef() 其 .current 属性被初始化为传入的参数(initialValue)// 所以useRef的初始化数据类型和useImperativeHandle返回的handle对象数据类型是一致的const publishArticleFormRef = useRef<IFormCompExportData>(null);const test = () => {const { getFieldsValue } = publishArticleFormRef.current as IFormCompExportData;// 获取表单的所有值getFieldsValue(true)console.log('表单收集的值', getFieldsValue(true));}return (<PageContainer><BaseFormformOptions={publishArticleFormOptions}formItemOptions={publishArticleFormData}formValue={publishArticleFormValue}ref={publishArticleFormRef}/><Button type="primary" onClick={test}>获取表单动态值</Button></PageContainer>);
};export default PublishArticle;
相关文章:
React hook+AntD pro实现Form表单的二次封装
React hookAntD pro实现Form表单的二次封装 封装Form表单1、在src/types下新建 antd/form/index.ts,进行Form表的配置、数据等类型的限制2、在 根目录/components 下新建 BaseForm/index.tsx文件3、在BaseForm/createFormIpt.tsx中,抽取对不同类型的表单…...
python异步切片下载文件(内置redis获取任务 mongo更新任务状态等)
异步切片下载二进制文件并上传桶删除本地文件 import json import os import asyncio from urllib import parseimport aiohttp import aioredis from motor.motor_asyncio import AsyncIOMotorClient from retrying import retry from minio import Minio from minio.error im…...

《吐血整理》进阶系列教程-拿捏Fiddler抓包教程(10)-Fiddler如何设置捕获Firefox浏览器的Https会话
1.简介 经过上一篇对Fiddler的配置后,绝大多数的Https的会话,我们可以成功捕获抓取到,但是有些版本的Firefox浏览器仍然是捕获不到其的Https会话,需要我们更进一步的配置才能捕获到会话进行抓包。 2.宏哥环境 1.宏哥的环境是Wi…...

阿里云云原生弹性方案:用弹性解决集群资源利用率难题
作者:赫曦 随着上云的认知更加普遍,我们发现除了以往占大部分的互联网类型的客户,一些传统的企业,一些制造类的和工业型企业客户也都开始使用云原生的方式去做 IT 架构的转型,提高集群资源使用率也成为企业上云的一致…...

Spring-BeanPostProcessor PostConstruct init InitializingBean 执行顺序
执行顺序探究 新建一个对象用于测试 Component public class Student implements InitializingBean {private String name;private int age;public String getName() {return name;}public void setName(String name) {this.name name;}public int getAge() {return age;}pu…...

【算法】递归
递归 递归初始递归:数列求和递归的应用:任意进制转换递归深度限制递归可视化:分形树递归可视化:谢尔宾斯基Sierpinski三角形递归的应用:汉诺塔递归的应用:探索迷宫 分治策略和递归优化问题兑换最少个数硬币…...

DC-1靶机刷题记录
靶机下载地址: 链接:https://pan.baidu.com/s/1GX7qOamdNx01622EYUBSow?pwd9nyo 提取码:9nyo 参考答案: https://c3ting.com/archives/kai-qi-vulnhnbshua-tiDC-1.pdf【【基础向】超详解vulnhub靶场DC-1】 https://www.bilibi…...

rust跟我学七:获取外网IP地址
图为RUST吉祥物 大家好,我是get_local_info作者带剑书生,这里用一篇文章讲解get_local_info是怎么获取到本机的外网IP地址。 首先,先要了解get_local_info是什么? get_local_info是一个获取linux系统信息的rust三方库,并提供一些常用功能,目前版本0.2.4。详细介绍地址:[…...
华为:交换机忘记console密码重置
一、背景 许多旧项目经过长时间使用后,因为没有特定的管理运维人员,初始对接人也将初始账号密码等重要信息丢失,现需要进后台查看配置或更改网络配置,需重置密码 二、重置密码,不重置设备方法 1、使用console插入交…...

2024年甘肃省职业院校技能大赛信息安全管理与评估 样题三 模块一
竞赛需要完成三个阶段的任务,分别完成三个模块,总分共计 1000分。三个模块内容和分值分别是: 1.第一阶段:模块一 网络平台搭建与设备安全防护(180 分钟,300 分)。 2.第二阶段:模块二…...

Go 中 slice 的 In 功能实现探索
文章目录 遍历二分查找map key性能总结 之前在知乎看到一个问题:为什么 Golang 没有像 Python 中 in 一样的功能?于是,搜了下这个问题,发现还是有不少人有这样的疑问。 补充:本文写于 2019 年。GO 现在已经支持泛型&am…...
pyDAL一个python的ORM(终) pyDAL的一些性能优化
一、大批量插入数据 对于 大量数据插入时,虽然pyDAL也手册中有个方法:bulk_insert(),但是手册也说了,虽然方法上是一次可以多条数据,如果后端数据库是关系型数据库,他转换为SQL时它是一条一条的插入的&…...
springboot log4j配置xml实例说明
提供样本配置代码 xml <?xml version"1.0" encoding"UTF-8"?> <!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL --> <!-- status log4j2内部日志级别 --> <configurat…...

VsCode重新安装需要配机的ESLint和 Prettier - Code formatter 配置
新电脑安装完Vscode后,需要装几个插件,这里记录下: {"diffEditor.ignoreTrimWhitespace": false,"files.autoSave": "afterDelay","editor.codeActionsOnSave": {"source.fixAll.eslint"…...

录屏功能怎么打开?简单操作,一学就会!
录屏功能在当今互联网时代变得越来越重要,无论是游戏录制、在线课程录制还是屏幕操作演示,录屏功能都为我们提供了便捷的解决方案。可是您知道录屏功能怎么打开吗?接下来,让我们一起探索如何在电脑上开启录屏功能,记录…...
小程序显示兼容处理,home键处理
定义: env(safe-area-inset-bottom)和env(safe-area-inset-top)是CSS中的变量,用于获取设备底部和顶部安全区域的大小 示例: padding-bottom: calc(env(safe-area-inset-bottom) 12px); /* 兼容iOS> 11.2 */安全间距类型: …...

【java八股文】之JVM基础篇
【java八股文】之JVM基础篇-CSDN博客 【java八股文】之MYSQL基础篇-CSDN博客 【java八股文】之Redis基础篇-CSDN博客 【java八股文】之Spring系列篇-CSDN博客 【java八股文】之分布式系列篇-CSDN博客 【java八股文】之多线程篇-CSDN博客 【java八股文】之JVM基础篇-CSDN博…...

2024美赛数学建模思路 - 案例:异常检测
文章目录 赛题思路一、简介 -- 关于异常检测异常检测监督学习 二、异常检测算法2. 箱线图分析3. 基于距离/密度4. 基于划分思想 建模资料 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 一、简介 – 关于异常…...

【EI会议征稿通知】2024年通信技术与软件工程国际学术会议 (CTSE 2024)
2024年通信技术与软件工程国际学术会议 (CTSE 2024) 2024 International Conference on Communication Technology and Software Engineering (CTSE 2024) 2024年通信技术与软件工程国际学术会议 (CTSE 2024)将于2024年03月15-17日在中国长沙举行。会议专注于通信技术与软件工…...
Js面试之作用域与闭包
Js面试之作用域与闭包 作用域词法作用域动态作用域 闭包闭包使用场景封装私有变量模块化开发保持变量状态异步操作 注意事项 最近在整理一些前端面试中经常被问到的问题,分为vue相关、react相关、js相关、react相关等等专题,可持续关注后续内容ÿ…...

SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...
Qt Widget类解析与代码注释
#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码,写上注释 当然可以!这段代码是 Qt …...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...
爬虫基础学习day2
# 爬虫设计领域 工商:企查查、天眼查短视频:抖音、快手、西瓜 ---> 飞瓜电商:京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空:抓取所有航空公司价格 ---> 去哪儿自媒体:采集自媒体数据进…...

select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...

html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)
Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习) 一、Aspose.PDF 简介二、说明(⚠️仅供学习与研究使用)三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...