|
2 | 2 |
|
3 | 3 | `npm install --save react-widget-form` |
4 | 4 |
|
| 5 | +```ts |
| 6 | +import { |
| 7 | + Form, |
| 8 | + FormItem, |
| 9 | + NativeInput, |
| 10 | + FormContext, |
| 11 | + FormItemContext, |
| 12 | + useForm, |
| 13 | + useFormItem |
| 14 | +} from 'react-widget-form' |
| 15 | + |
| 16 | +``` |
| 17 | + |
5 | 18 | ## Props |
6 | 19 |
|
| 20 | +### Types |
| 21 | + |
| 22 | +```ts |
| 23 | +type ValidateTriggerType = "change" | "blur"; |
| 24 | + |
| 25 | +type Validator = ( |
| 26 | + value: any, |
| 27 | + formValue: {} |
| 28 | +) => boolean | string | Error | Promise; |
| 29 | + |
| 30 | +type InvalidError = { |
| 31 | + name: string; |
| 32 | + message: any; |
| 33 | +}; |
| 34 | + |
| 35 | +``` |
| 36 | + |
7 | 37 | ### Form |
8 | | -| 参数 | 说明 | 类型 | 默认值 | |
9 | | -| --- | --- | --- | --- | |
10 | | -| prefixCls | 组件CSS样式前缀 | string | rw-form | |
11 | | -| className | 组件className属性 | string | - | |
12 | | -| style | 组件style属性 | React.CSSProperties | - | |
13 | | -| path2obj | 是否启用lodash.get、是否启用lodash.set来获取、设置formValue的值 | boolean | true | |
14 | | -| defaultFormValue | 表单默认数据 | object | {} | |
15 | | -| formValue | 表单数据`受控` | object | | |
16 | | -| validateDelay |- | number | | |
17 | | -| validateTrigger |- | string | | |
18 | | -| validateFieldsAndScroll |- | string | | |
19 | | -| showMessage |- | string | | |
20 | | -| component | 表单默认元素 | React.Element | form | |
21 | | -| rules | 验证规则 | object\|array\|function | null | |
22 | | -| labelWidth | 表单标签域宽度 | number\|string | - | |
23 | | -| labelPosition | 表单标签域位置 | `top` `left` `right` | left | |
24 | | -| alignItems | 表单控制表单项的alignItems的属性 | string | center | |
25 | | -| inline | 行内表单模式 | function(value,e) | | |
26 | | -| onSubmit | 只有当原生表单的onSubmit事件 | function(e) | | |
27 | | -| onChange | 按下回车的回调 | function(formValue, e) | | |
28 | | -| getFormItemInputProps | 自定义表单输入框控件的属性 | function(e) | | |
29 | 38 |
|
| 39 | +```ts |
| 40 | +children: ((form: Form) => React.ReactNode) | React.ReactNode; |
| 41 | +prefixCls?: string; |
| 42 | +className?: string; |
| 43 | +style?: React.CSSProperties; |
| 44 | +path2obj?: boolean; |
| 45 | +defaultFormValue?: {}; |
| 46 | +formValue?: {}; |
| 47 | +getDefaultFieldValue?: (name: string) => any; |
| 48 | +renderFieldExtra?: ( |
| 49 | + component: FormItem, |
| 50 | + name: string |
| 51 | +) => React.ReactNode; |
| 52 | +validators?: { |
| 53 | + [name: string]: Validator | Validator[]; |
| 54 | +}; |
| 55 | +validateDelay?: number; |
| 56 | +validateTrigger?: ValidateTriggerType | ValidateTriggerType[]; |
| 57 | +asyncTestDelay?: number; |
| 58 | +component?: React.ElementType; |
| 59 | +labelWidth?: string | number; |
| 60 | +labelClassName?: string; |
| 61 | +labelStyle?: React.CSSProperties; |
| 62 | +labelPosition?: "top" | "left"; |
| 63 | +controlStyle?: React.CSSProperties; |
| 64 | +controlClassName?: string; |
| 65 | +clearErrorOnFocus?: boolean; |
| 66 | +inline?: boolean; |
| 67 | +onSubmit?: (e: React.SyntheticEvent) => void; |
| 68 | +onChange?: (formValue: {}) => void; |
| 69 | +getInputProps?: (component: FormItem, name: string) => {}; |
| 70 | +``` |
30 | 71 |
|
31 | 72 | ### FormItem |
32 | | -| 参数 | 说明 | 类型 | 默认值 | |
33 | | -| --- | --- | --- | --- | |
34 | | -| - | - | - | - | |
35 | | -| - | - | - | |
36 | 73 |
|
37 | | -### NativeField |
38 | | -| 参数 | 说明 | 类型 | 默认值 | |
39 | | -| --- | --- | --- | --- | |
40 | | -| component | 接收`value` `onChange(e)`的控件 | React.Element | input | |
| 74 | +```ts |
| 75 | +children: |
| 76 | + | ((props: FormItemChildProps, item: FormItem) => React.ReactNode) |
| 77 | + | React.ReactNode; |
| 78 | +prefixCls?: string; |
| 79 | +name?: string; |
| 80 | +className?: string; |
| 81 | +style?: React.CSSProperties; |
| 82 | +validator?: Validator | Validator[]; |
| 83 | +label?: React.ReactNode; |
| 84 | +labelFor?: string; |
| 85 | +labelWidth?: string | number; |
| 86 | +labelClassName?: string; |
| 87 | +labelStyle?: React.CSSProperties; |
| 88 | +labelPosition?: "top" | "left"; |
| 89 | +controlStyle?: React.CSSProperties; |
| 90 | +controlClassName?: string; |
| 91 | +required?: boolean; |
| 92 | +requiredMessage?: string; |
| 93 | +clearErrorOnFocus?: boolean; |
| 94 | +normalize?: (value: any) => any; |
| 95 | +renderExtra?: (component: FormItem) => React.ReactNode; |
| 96 | +validateDelay?: number; |
| 97 | +validateTrigger?: ValidateTriggerType | ValidateTriggerType[]; |
| 98 | +inline?: boolean; |
| 99 | +onChange?: (value: any) => void; |
| 100 | +onFocus?: (e: React.SyntheticEvent) => void; |
| 101 | +onBlur?: (e: React.SyntheticEvent) => void; |
| 102 | +``` |
| 103 | + |
| 104 | +FormItem的会覆盖child的部分属性,覆盖属性如下: |
| 105 | + |
| 106 | +如果child的值发生改变必须要调用`onChange`来更新`Form`的状态,同样child发生`focus` `blur`最好也要调用`onFocus` `onBlur` |
| 107 | + |
| 108 | +- 【重要】 `onChange` 会触发 `validateTrigger` 及 Form的`onChange` |
| 109 | +- `onFocus` 会触发`clearErrorOnFocus`行为 |
| 110 | +- `onBlur` 会触发`validateTrigger`行为 |
| 111 | + |
| 112 | +```ts |
| 113 | +{ |
| 114 | + value: any; |
| 115 | + onChange: (value: any) => void; |
| 116 | + onFocus: (e: React.SyntheticEvent) => void; |
| 117 | + onBlur: (e: React.SyntheticEvent) => void; |
| 118 | + [propName: string]: any; |
| 119 | +} |
| 120 | +``` |
| 121 | + |
| 122 | +由于FormItem的`onChange`接收的是一个值,所以不能直接使用原生表单组件或其他并非直接提供值的组件,例如: |
| 123 | +```jsx |
| 124 | +//这是错误的,onChange会将Event当作值赋值给formValue,可能导致预期不一致 |
| 125 | +//ERROR |
| 126 | +<FormItem name="email"> |
| 127 | + <input type="text" /> |
| 128 | +</FormItem> |
| 129 | + |
| 130 | +//正确写法一: |
| 131 | +<FormItem name="email"> |
| 132 | + { |
| 133 | + (props) => { |
| 134 | + |
| 135 | + return <input {...props} type="text" onChange={e => props.onChange(e.target.value)} /> |
| 136 | + } |
| 137 | + } |
| 138 | +</FormItem> |
| 139 | + |
| 140 | +//正确写法二: |
| 141 | +function Input(props){ |
| 142 | + return <input {...props} type="text" onChange={e => props.onChange(e.target.value)} /> |
| 143 | +} |
| 144 | +<FormItem name="email"> |
| 145 | + <Input /> |
| 146 | +</FormItem> |
| 147 | + |
| 148 | +//正确写法三,使用NativeInput: |
| 149 | +<FormItem name="email"> |
| 150 | + <NativeInput component="input" /> |
| 151 | +</FormItem> |
| 152 | +``` |
| 153 | + |
| 154 | + |
| 155 | +### NativeInput |
| 156 | + |
| 157 | +```ts |
| 158 | +component: React.ElementType; |
| 159 | +onChange?: (value: any) => void; |
| 160 | +inputRef?: (dom: any) => void; |
| 161 | +[others: string]: any; |
| 162 | +``` |
| 163 | + |
| 164 | +> others 会传递给component组件 |
| 165 | +
|
| 166 | +`NativeInput`是为了解决`onChange`返回事件的情况下做了简单的处理,封装代码如下: |
| 167 | +```js |
| 168 | +export default function NativeInput(props) { |
| 169 | + const { |
| 170 | + component: Component = "input", |
| 171 | + value, |
| 172 | + inputRef, |
| 173 | + onChange, |
| 174 | + ...others |
| 175 | + } = props; |
| 176 | + |
| 177 | + const onInputChange = e => { |
| 178 | + const value = e.target.value; |
| 179 | + onChange && onChange(value, e); |
| 180 | + }; |
| 181 | + |
| 182 | + return ( |
| 183 | + <Component |
| 184 | + ref={inputRef} |
| 185 | + onChange={onInputChange} |
| 186 | + value={value} |
| 187 | + {...others} |
| 188 | + /> |
| 189 | + ); |
| 190 | +} |
| 191 | + |
| 192 | +``` |
| 193 | + |
| 194 | +## Methods |
| 195 | + |
| 196 | +### Form |
| 197 | +```ts |
| 198 | +{ |
| 199 | + getValue(name: string): any; |
| 200 | + setValue( |
| 201 | + name: string, |
| 202 | + value: any, |
| 203 | + callback: (formValue: {}) => void |
| 204 | + ): void; |
| 205 | + setValues(formValue: {}, callback: (formValue: {}) => void): void; |
| 206 | + hasError(name: string): boolean; |
| 207 | + getError(name: string): any; |
| 208 | + cleanError(name: string): void; |
| 209 | + setError(name: string): void; |
| 210 | + cleanErrors(): void; |
| 211 | + setErrors(errors: {}): void; |
| 212 | + isFieldValidating(name: string): boolean; |
| 213 | + isValidating(): boolean; |
| 214 | + validateField( |
| 215 | + name: string, |
| 216 | + callback: (errors: null | InvalidError[], formValue: {}) => void |
| 217 | + ): boolean; |
| 218 | + validate( |
| 219 | + callback: (errors: null | InvalidError[], formValue: {}) => void |
| 220 | + ): boolean; |
| 221 | + validateAndScroll( |
| 222 | + callback: (errors: null | InvalidError[], formValue: {}) => void |
| 223 | + ): boolean; |
| 224 | +} |
| 225 | +``` |
| 226 | + |
| 227 | +### FormItem |
| 228 | +```ts |
| 229 | +{ |
| 230 | + getDOM(): any; |
| 231 | + getForm(): Form; |
| 232 | + getValue(): any; |
| 233 | + setValue(value: any, callback: (formValue: {}) => void): void; |
| 234 | + hasError(): boolean; |
| 235 | + getError(): any; |
| 236 | + cleanError(): void; |
| 237 | + setError(message: any): void; |
| 238 | + isValidating(): boolean; |
| 239 | + validate( |
| 240 | + callback: (errors: null | InvalidError[], formValue: {}) => void |
| 241 | + ): boolean; |
| 242 | +} |
| 243 | +``` |
| 244 | + |
| 245 | +## hooks |
| 246 | + |
| 247 | +- useForm |
| 248 | +- useFormItem |
| 249 | + |
| 250 | + |
| 251 | +## 基础样式 |
| 252 | + |
| 253 | +```scss |
| 254 | +$form-item-cls: nex-form-item; |
| 255 | + |
| 256 | +.#{$form-item-cls} { |
| 257 | + display: flex; |
| 258 | + |
| 259 | + &-inline { |
| 260 | + display: inline-flex; |
| 261 | + } |
| 262 | + |
| 263 | + &-label { |
| 264 | + text-align: right; |
| 265 | + flex: none; |
| 266 | + } |
| 267 | + |
| 268 | + &-top { |
| 269 | + display: block; |
| 270 | + } |
| 271 | + |
| 272 | + &-top.#{$form-item-cls}-inline { |
| 273 | + display: inline-block; |
| 274 | + vertical-align: top; |
| 275 | + } |
| 276 | + |
| 277 | + &-top &-label { |
| 278 | + text-align: left; |
| 279 | + display: block; |
| 280 | + } |
| 281 | + |
| 282 | + &-control { |
| 283 | + position: relative; |
| 284 | + flex: 1; |
| 285 | + } |
| 286 | + |
| 287 | + &.is-required &-label:before { |
| 288 | + content: "*"; |
| 289 | + display: inline-block; |
| 290 | + margin-right: 4px; |
| 291 | + font-family: SimSun; |
| 292 | + color: red; |
| 293 | + } |
| 294 | +} |
| 295 | + |
| 296 | +``` |
| 297 | + |
41 | 298 |
|
42 | | -其余属性传递给component。 |
43 | 299 |
|
0 commit comments