@jzl/aa-form
v0.0.6
Published
## 起因
Downloads
10
Readme
auto-antd-form
起因
Form 使用双向绑定,开发效率高,代码可读性好。
双向绑定表达,表达简单直观。支持嵌套字段
提供 validate 机制,配合
<FormContext>
和<FormButton>
, 自动管理相关状态。组件使用方式和 antd 一致,几乎没有学习成本,可以直接参考 antd 的文档。
扩展性强,符合 value,onChange 模式的组件,通过简单的包装,可以快速融入进这套模式中
性能。每次修改,只有被编辑的那个组件会触发渲染,form 再大,也不会有性能问题。
使用
- 首先安装 react react-dom immer -react antd
- yarn add @jzl/aa-form
- 如果使用 antd 的按需加载,为了样式生效,需要在 webpack 的 modules 的 rules 中 配置添加
{
test: /node_modules[\\/]@jzl[\\/]aa-form[\\/].*\.(j|t)sx?$/,
use: {
loader: "babel-loader",
options: {
// your options
}
}
},
Basic Usage
import { FormContext, FormInput, FormCheckbox } from '@jzl/aa-form';
// function component
return (
<FormContext
initState={{
text: '',
done: false,
}}
>
<FormInput
className="input-class"
label="text"
path="text"
rules={(value: string) => {
// return 非空字符串表示验证有错误,提示就是这个字符串
if (value === 'todo') {
return '不能输入 todo';
}
}}
placeholder="输入todo文本"
/>
<FormCheckbox label="done" path="done" />
</FormContext>
);
一个复杂的例子
FormContext
// 使用 state 为受控模式,需要在 onContextChange 对state 进行更新
// 传入state后,会忽略 initState
{
initState?: M;
state?: M;
validateAtFirst?: boolean; // 默认是点击过 FormButton 后才开始做validate 检查,如果开始就要检查,设置为true
onSubmit({ state }: { state: M }, e: React.FormEvent<HTMLFormElement>): void; // 只有 validate 检查成功后,才会触发
onContextChange?({ state }: { state: M }): void; // 这个form的state,有任何的改变
}
提供的组件和设施 (待添加)
- 组件
FormInput, FormTextArea,FormInputNumber
FormCheckbox
FormSelect, FormRadioGroup, FormTagGroup
FormDate, FormDateRange
- 设施
// 下面两个用于提供上下文(公共model),状态的检验和 submit 事件等
FormContext: 提供共享上下文,比如 model(如果组件提供的 model,优先级更改), 一些通用样式,比如 label 占多宽
FormButton: 和 FormContext 配合,自动管理验证和提交
FormWrapper: 自定义复杂类型,比如需要动态修改的数组,Map。请参考本文档的 `一个复杂的例子`.
API
From
组件,如 Input, Select, Radio 等,
export type ValidateFn<M> = ((value: any, model: M) => string | void) | string;
export interface ICommonOption {
key?: string;
title: string;
value: any;
}
// 通用属性如下
// 一般情况,你只需要关注2,3个属性
{
path?: string; // 字段名
onChange?(param: IChangeParam<M>): void; // onChange 事件,此时 value 已经修改
beforeChange?(
param: IChangeParam<M> & {
oldValue?: any;
},
): boolean | void; // change 发生前,可以拿到 old value. 函数return false, 阻止修改
transformViewToModel?(value: any, props: ICommonFormOuterProps<M>): any;
transformModelToView?(mValue: any, props: ICommonFormOuterProps<M>): any;
label?: string | React.ReactNode;
itemProps?: FormItemProps; // antd Form.Item 的 props
noFormItem?: boolean; // 默认所以的组件都会包裹在 <Form.Item>里,设置 true,直接返回组件
rules?: ValidateFn<M> | ValidateFn<M>[]; // validate 规则
suffixTip?: React.ReactNode; // 组件后面的提示文案
[x: string]: any; // 其他组件属性
}
FormWrapper 要求 children 是一个函数,函数的参数如下 model 定义如下
export type IAaFormModel<M> = {
state: M; // 最新的 state
setKey(key: string, value: any): M; // 修改某一个字段,返回新的 state
update(updateFn: (draft: Draft<M>) => void): M; // 包装了 immer 的produce,在函数里直接修改 state,返回新的 state
};
Validate
在组件上添加 rules 接受 (value: any, Model: M) => string | any
返回值只要是非空字符串,就表明出错,提示信息就是返回的字符串
// yourRuleFn 接受 value, 以及 state: M, 通过这两个
// 返回值只要是非空字符串,就表明出错,
<FormInput path="text" rules={yourRuleFn} />
点击按钮后,检查所有规则,如果有错,阻止提交,给出提示(提示的样式见 antd Form.Item) 同时 disable FormButton
,直到满足所有规则。
组件可以自己提供 defaultRuleFn: (value, model) => string | any
通过 defaultRuleFn 去控制状态默认的的合法性,比如上传组件,正在上传中,最近的状态不是合法的,可以设置为 请等待上传完毕
。
对 Antd 的修改
- 统一 onChange 的参数(antd 中 Input 传的是 Event,CheckBox 传的 checked value)。不过双向绑定的机制,几乎不需要关注 onChange 方法。
- FormDate 默认的 value 是时间戳,为 number 类型,13 位数字。传入
unix={true}
value 是 10 位数字。 - label 直接设置,其他 Antd 的 Form.Item 的属性,通过 itemProps 传入, 具体见antd 文档
- 所有接受选项的组件,统一成传入
options
数组, 每一项提供 title 和 value{ title: string, value: number|string }
, 便于生成代码生成
<FormInput label="input label" itemProps={...customItemProps}>
value 的取值规则
- 默认
_.get(mode, path)
(path 支持嵌套) - 组件提供,比如
FormDate
和FormDateRange
会把 antd 返回的 moment 改为 timestamp
function FormDate(props: IFormComponentProps) {// ...}
FormDate.transformModelToView = function(timestamp: number, props: IProps) {
// 把model上的value,转成antd 需要的moment
};
FormDate.transformViewToModel = function(momentInst: Moment, props: IProps) {
// 把 antd 组件的 moment 转成时间戳
};
- 使用组件时传入
transformModelToView
和transformViewToModel
上面 3 个规则,优先级越来越高。
自定义
只要符合 value, onChange 模式的组件,可以快速融入这套体系,比如基于react-color
的改造,只需要下面几行代码。
import * as React from 'react';
import { FormRender } from '@jzl/auto-form';
import { SketchPicker, ColorResult } from 'react-color';
import { IRenderProps } from '@jzl/auto-form/lib/form-render';
import { ICommonFormOuterProps } from '@jzl/auto-form/lib/types';
export function FormColor<M>(rawProps: ICommonFormOuterProps<M>) {
return (
<FormRender
{...rawProps}
render={(props: IRenderProps<M>) => {
function handleChange(e: ColorResult) {
props.onChange(e.hex);
}
return (
<SketchPicker onChangeComplete={handleChange} color={props.value} />
);
}}
></FormRender>
);
}