淮南网站建设费用,组建团队建设网站与开发需要多少钱,平台网站开发可行性分析,上海微信网站建设费用React hookAntD pro实现Form表单的二次封装 封装Form表单1、在src/types下新建 antd/form/index.ts#xff0c;进行Form表的配置、数据等类型的限制2、在 根目录/components 下新建 BaseForm/index.tsx文件3、在BaseForm/createFormIpt.tsx中#xff0c;抽取对不同类型的表单… React hookAntD 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.ts5、在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.Refany) {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 typepassword 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 useRefIFormCompExportData(null);const test () {const { getFieldsValue } publishArticleFormRef.current as IFormCompExportData;// 获取表单的所有值getFieldsValue(true)console.log(表单收集的值, getFieldsValue(true));}return (PageContainerBaseFormformOptions{publishArticleFormOptions}formItemOptions{publishArticleFormData}formValue{publishArticleFormValue}ref{publishArticleFormRef}/Button typeprimary onClick{test}获取表单动态值/Button/PageContainer);
};export default PublishArticle;