文章目录

  • 一、form表单封装之树形选择框封装
    • 1. 代码结构
      • (1)html代码
      • (2)树形选择框的结构
      • (3)css
      • (4)转化函数
    • 2. 使用方法
      • (1)单独使用
      • (2)和form表单一起使用
  • 二、form表单之时间范围选择器封装
    • 1. 代码
      • (1)html代码
    • 2. 使用方法
      • (1)单独使用
      • (2)在form表单中使用
  • 三、form表单封装
    • 1. 代码
      • (1)html
      • (2)数据结构
      • (3)css
    • 2. 使用方法
      • (1)导入该组件
      • (2)表单提交方法
        • a. 使用了时间选择框
        • b. 没有使用时间选择框
      • (3)formData数据
      • (4)其他

前提说一下,我使用的ui组件是React-antd

一、form表单封装之树形选择框封装

树形选择框对应于antd的 https://ant.design/components/tree-select-cn/

1. 代码结构

(1)html代码

代码如下:

import React, { FC, forwardRef } from 'react';
import { MarketList } from 'utils/convertToTreeData';
import { TreeSelect } from 'antd';
import styles from './tree-picker.module.scss';
import { TreeSelectProps } from 'antd/lib/tree-select';
import { TreeNodeValue } from 'antd/lib/tree-select/interface';//定义树形选择框所使用的prop
interface ComPonentProps<T extends TreeNodeValue> {style?: object;loading?: boolean;treeData: MarketList[];placeholder?: string;value?: TreeNodeValue;onChange?: TreeSelectProps<T>['onChange'];
}
type Props = ComPonentProps<TreeNodeValue>;
const TreePicker: FC<Props> = ({ onChange, value, style, loading, treeData, placeholder }, ref): React.ReactElement => {return (<><TreeSelectclassName={styles['tree-select']} //css做样式调整loading={loading}style={style}treeData={treeData}treeCheckable={true}placeholder={placeholder}onChange={onChange}ref={ref}value={value}></TreeSelect></>);
};
export default forwardRef(TreePicker);

(2)树形选择框的结构

MarketList 的结构如下:

interface MarketItem {key: string;value: string;title: string;
}
export interface MarketList {key: string;value: string;title: string;children: MarketItem[];
}

(3)css

我用的是scss
css如下:

.tree-select {:global .ant-select-selection {height: 30px;overflow-y: scroll;}
}

(4)转化函数

注意在使用树形选择框时,需要数据转化为MarketList的形式,转化函数如下:
先调用father函数转化大致格式,再将其转化为树形选择框的形式

//以下函数对我的数据有用,对自己的数据可以改变形式
//我的数据格式如下:
/*
[{"group": {"id": "5f2b9d0832326e014cfe862a","parentId": "5f2b9d0832326e014cfe862a","rootId": "5f2b9d0832326e014cfe862a","groupName": "测试设备"},"devices": [{"id": "5f4f8863afc2140186e27b17","deviceId": "18:93:7F:B3:55:98","deviceName": "444-2"},{"id": "5f63097fafc2140186e27b18","deviceId": "18:93:7F:94:D4:4D","deviceName": "333"},{"id": "5fa3ab7ff34acc03cf0d2c99","deviceId": "18:93:7F:B3:34:94","deviceName": "5555"},{...}]},{...}
]
*/
//将数据结构统一
export function convertToFatherTreeData(list: any[]): MarketList[] {list.forEach(item => {item.deviceName = item.group.groupName;item.deviceId = item.group.rootId;item.id = item.group.id;item.children = item.devices;delete item.devices;delete item.group;});return list;
}
//将数据转成antd所需要的格式
export function convertToTreeData(list: any[]): MarketList[] {list.forEach(item => {item.title = item.deviceName;item.value = item.deviceId;item.key = item.id;delete item.deviceName;delete item.deviceId;delete item.id;if (item.children && item.children.length) {convertToTreeData(item.children);}});return list;
}

2. 使用方法

(1)单独使用

这里先介绍独立的使用方法

<Col span={6}><label style={{ verticalAlign: 'top', lineHeight: '31px' }}>范围:</label><TreePickeronChange={handleDeviceChange}loading={loading}treeData={deviceArea} //转化好的数据,这里就不做赘述style={{ width: '70%' }}placeholder={'请选择范围'}/>
</Col>

onchange函数

//可以将数据直接保存在state数组中const handleDeviceChange = useCallback(value => {setDeviceGroup(value);},[setDeviceGroup],);

(2)和form表单一起使用

这里不使用onChange函数,可以使用form的onSubmit/onFinish函数就可以拿到group的值

  <Form.Item label={'范围'}  >{getFieldDecorator(`group`, {initialValue: group,//默认数据})(<TreePickerloading={loading}treeData={deviceArea} //转化好的数据,这里就不做赘述placeholder={ `请选择范围`}/>,)}</Form.Item>

二、form表单之时间范围选择器封装

1. 代码

(1)html代码

import React, { FC, useCallback, forwardRef } from 'react';
import moment from 'moment';
import { DatePicker } from 'antd';
import { RangePickerValue, RangePickerProps } from 'antd/lib/date-picker/interface';const { RangePicker } = DatePicker;interface ComPonentProps {style?: object;value?: RangePickerValue;onChange?: RangePickerProps['onChange'];
}
type Props = ComPonentProps;const TimePicker: FC<Props> = ({ style, onChange, value }, ref): React.ReactElement => {//设置今天以后的日期不可选const disabledStartDate = useCallback(current => {return current && current > moment().endOf('day');}, []);return (<><RangePickerstyle={style}showTime={{ format: 'YYYY-MM-DD HH:mm:ss' }}format="YYYY-MM-DD HH:mm:ss"placeholder={['起始时间', '结束时间']}disabledDate={disabledStartDate}onChange={onChange}ref={ref}value={value}/></>);
};
export default forwardRef(TimePicker);

2. 使用方法

(1)单独使用

通过onChange函数就可以拿到数据

<col span={6}><label>时间选取:</label><TimePicker  onChange={handleOnchange} />
</col>

(2)在form表单中使用

这里不使用onChange函数,可以使用form的onSubmit/onFinish函数就可以拿到起始时间和结束时间

  <Form.Item label={'时间范围'}  >{getFieldDecorator(`group`, {initialValue: group,//默认数据})(<TimePicker/>)}</Form.Item>

三、form表单封装

1. 代码

(1)html

import React, { FC, useCallback, useRef, ReactNode } from 'react';
import { ActionItem } from './form-types';
import { Input, Select, Button } from 'antd';
import Form, { FormComponentProps } from 'antd/lib/form';
import TimePicker from 'components/time-picker';
import TreePicker from 'components/tree-picker';
import styles from './form-basic.module.scss';const { Option } = Select;interface ComponentProps {actions: ActionItem[];onSubmit(value?: ActionItem['value']): void;render?(value?: ReactNode): void;method?: string;
}
type Props = FormComponentProps & ComponentProps;
const FormCustom: FC<Props> = ({ actions, method, form, children, onSubmit, render }): JSX.Element => {const { getFieldDecorator, setFieldsValue } = form;const TimePickerRef = useRef(null);const TreePickerRef = useRef(null);const renderForm = useCallback((item, index) => {switch (item.type) {case 'input':return (<Form.Item key={index} label={item.label}>{getFieldDecorator(`${item.name}`, {initialValue: item.value || '',rules: [{ required: item.required, message: `请输入${item.label}` }],})(<Input placeholder={item.placeholder || `请输入${item.label}`} style={item.style} />)}</Form.Item>);case 'select':return (<Form.Item label={item.label} key={index}>{getFieldDecorator(`${item.name}`, {initialValue: item.value || '',rules: [{ required: item.required, message: `请选择${item.label}` }],})(<Select style={item.style} placeholder={item.placeholder || `请选择${item.label}`}>{item.options.map((o: any, i: any) => {return (<Option key={i} value={o.value}>{o.label}</Option>);})}</Select>,)}</Form.Item>);case 'timePicker':return (<Form.Item label={item.label} key={index}>{getFieldDecorator(`${item.name}`, {initialValue: item.value,})(<TimePicker style={item.style} ref={TimePickerRef} />)}</Form.Item>);case 'treePicker':return (<Form.Item label={item.label} key={index} className={styles['tree-basic']}>{getFieldDecorator(`${item.name}`, {initialValue: item.value,})(<TreePickerstyle={item.style}ref={TreePickerRef}treeData={item.treeOptions}placeholder={item.placeholder || `请选择${item.label}`}/>,)}</Form.Item>);}},[getFieldDecorator],);const handleSubmit: React.FormEventHandler<HTMLFormElement> = useCallback((e): void => {e.preventDefault();form.validateFields((err, values) => {if (!err) {onSubmit(values);}});},[form, onSubmit],);return (<div><Form layout="inline" onSubmit={handleSubmit}>{actions.map((item: ActionItem, index: number) => {return renderForm(item, index);})}{children}<Form.Item><Button type="primary" htmlType="submit">{method ? method : '搜索'}</Button></Form.Item>{render && render()}</Form></div>);
};
export default FormCustom;

(2)数据结构

import { MarketList } from 'utils/convertToTreeData';//前面已经给了
import moment from 'moment';
type ValueForm = string | null | undefined | moment.Moment;
export interface ActionItem {type: string;name: string;label: string;value: ValueForm | ValueForm[];min?: number;max?: number;required?: boolean;placeholder?: string;options?: ActionOptionsItem[];treeOptions?: MarketList[];style?: {};
}
export interface ActionOptionsItem {value: string;label: string;
}

(3)css

使用的css较少

.tree-basic {margin-top: 4px;
}

2. 使用方法

(1)导入该组件

<FormCustomonSubmit={handleSubmit} //提交表单的方法form={form}actions={formData} //显示该表单的遍历数据render={(): ReactNode => {return (//在这里可以在搜索的button后面增加其他的button,不会影响美观【跑到搜索button前面】<Form.Item><Button type="primary" style={{ marginLeft: 8 }} onClick={handleImportBtnClick}>我是其他的button</Button></Form.Item>);}}>//在这里可以增加其他表单<Form.Item label={'我是其他表单'}>{getFieldDecorator('xxx', {rules: [{ required: true, message: '请选择' }],})(<Select style={{ width: 130 }} placeholder={'请选择'} onChange={handleBizCodeChange}>{groups.map((item): JSX.Element => {return (<Option value={item.value} key={item.key}>{item.name}</Option>);},)}</Select>,)}</Form.Item></FormCustom>

(2)表单提交方法

a. 使用了时间选择框

需要将时间选择不以数据形式展示的,需要拿出来。【对应于上面,如果时间选择框在form.item中使用一样】

  const handleSubmit = (values: any): void => {const {timeRange: [from, to],...rest} = values;console.log({...rest,from: from ? moment(from._d).format('YYYY-MM-DD HH:mm:ss') : '',to: to ? moment(to._d).format('YYYY-MM-DD HH:mm:ss') : '',});};

b. 没有使用时间选择框

直接可以拿到数据

  const handleSubmit = (values: any): void => {console.log(values)};

(3)formData数据


//ActionItem上面有定义const formData: ActionItem[] = [{type: 'input',label: '姓名',value: name || '',name: 'name',},{type: 'select',label: '下拉框',value: limitStatus || 'permit',name: 'limitStatus',options: STATUS_TYPES,style: { width: '80px' },},{type: 'timePicker',label: '时间选择框',value: [timeJudge(from as string), timeJudge(to as string)],name: 'timeRange',},{type: 'treePicker',label: '树形选择框',//判断数据是否存在,如果转成字符串,则需要转会来//value: (limitType as string) ? (limitType as string).split(',') : [],//没有转成字符串则不需要,只需要判断是否为空就行value: limitType || [],name: 'limitType',treeOptions: LIMIT_TYPE,style: { width: '200px' },},];//下拉框数据格式const STATUS_TYPES = [{value: '',label: '全部',},{value: '111',label: '111',},{value: '222',label: '222',},];

(4)其他

有timeJudge函数,是我自己写的,用来判断初始值是否为空字符串

import moment from 'moment';export const timeJudge = (value: string): any => {if (value && value.length > 0) {return moment(value);} else {return undefined;}
};

综上,完成form表单封装,实践中就可以用了

React之Form表单封装相关推荐

  1. react antd form 表单清空

    关于react_antd_desgin的学习这两天也是获取到的知识零零散散,大多在网上也能获取的到,所以隔了很长的时间,没有编写关于react相关的文章.今天之所以写也是因为公司中秋节放假,在郑州,窗 ...

  2. React的form表单提交

    包括了表单里input radio select checkbox textarea form 等一些操作, import React,{Component} from 'react';class R ...

  3. jQuery——封装form表单的数据为json对象

    CDN <script src="https://cdn.jsdelivr.net/npm/jquery@3.4.1/dist/jquery.min.js" integrit ...

  4. 基于vue3 element plus form 表单的二次封装

    记录一下开发中对form表单的二次封装及使用 前言 在我们的日常工作中经常会使用到form表来满足提交需求,那么将form表单封装成组件将会大大提高我们的工作效率,避免更多重复代码的书写,只需一些简单 ...

  5. reac笔记_13 form表单元素中 input/defaultValue + useState/useRef

    目录 原生html元素 input属性 示例1 示例2 react中 受控组件与非受控组件 属性 error - input标签value属性使用 示例 - useState 示例 - input标签 ...

  6. js将form表单提交数据封装为ajax提交

    对于数据提交,html自带了form表单,以form表单里的input框的name为key值,以其所对应的value为value值,传给后台供其使用.但是这样的方法与ajax传输数据还是有许多差距: ...

  7. html+form+提交json数据,form表单提交json格式数据

    我的实践整理.java 方式一: 发送数据web $(':submit').on('click',function(){ $.ajax({ url:"buy", type:&quo ...

  8. form表单提交json格式数据

    参考自 jQuery实现ajax提交form表单(可以是提交json),用springmvc接收.图文详解 个人实践整理. 方式一: 发送数据 <script type="applic ...

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

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

最新文章

  1. linux 进程做成服务,Linux自定义后台服务进程
  2. ELFHash的理解
  3. “盗”亦有道,关于robots协议
  4. 电脑睡眠快捷键_电脑快速进入睡眠的快捷键是什么?
  5. 17张图带你解析红黑树的原理!保证你能看懂!
  6. 网页内嵌多媒体 IE,Mozilla、Firefox、NetScape、Opera
  7. PostgreSQL数据库——Pigsty pg_exporter
  8. centOS服务器 netstat命令 查看TCP连接数信息(转)
  9. ffmpeg 转换flv压缩大小_ffmpeg 视频压缩 转换
  10. Intent的设想与天马行空
  11. 女生也玩橄榄球?而且还有世界杯?!
  12. 【Android Studio】如果你不管怎么折腾都提示Minimum supported Gradle version is 7.0.2. Current version is 6.8,请看这里
  13. imx6ull移植Linux系统第二篇——Linux内核的移植
  14. 云计算——Google云计算原理与应用(Google文件系统GFS)
  15. bytearray函数
  16. JAVA计算机毕业设计东理咨询交流论坛Mybatis+源码+数据库+lw文档+系统+调试部署
  17. 【2】模块参数与模块之间的通信
  18. 中国移动机顶盒系统升级服务器地址,中国移动电视机顶盒WIFI网络设置步骤
  19. 鲁棒优化(4):通过yalmip中的kkt命令实现CCG两阶段鲁棒优化
  20. Openstack组件部署 — Networking service_安装并配置Controller Node

热门文章

  1. 实践 | 基于VGG-16实现中草药分类
  2. R网络爬虫之酒店团购
  3. Self-Attention for CodeSearch
  4. 计算机毕业设计题目大全(论文+源码)_kaic
  5. 阿里云服务器怎么更换操作系统?阿里云服务器更换操作系统文档
  6. Android获得火车时刻表Web Services的全部始发站名称
  7. 浏览器开发工具请求头与响应头属性介绍
  8. 计算机圣诞节教案,小班圣诞节教案三篇
  9. 绝地求生 服务器位置,绝地求生国服登陆界面地址入口 国服登陆界面地址在哪儿...
  10. 【数字图像处理】灰度变换函数(对数变换、反对数变换、幂次变换)