Skip to content

Commit 78dfd4b

Browse files
committed
1. 校验优先级调整,validate优先级高于validateField
1 parent 3f60c43 commit 78dfd4b

File tree

4 files changed

+59
-73
lines changed

4 files changed

+59
-73
lines changed

src/Form.tsx

Lines changed: 46 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import set from "lodash/set";
44
import get from "lodash/get";
55
import isFunction from "lodash/isFunction";
66
import FormContext from "./FormContext";
7-
import { FormItem, IFormItemProps } from "./FormItem";
7+
import { FormItem } from "./FormItem";
88
import { isEmptyValue } from "./utils";
99

1010
import {
@@ -34,6 +34,7 @@ export interface IFormProps {
3434
clearErrorOnFocus: boolean;
3535
inline: boolean;
3636

37+
scrollIntoView?: (dom: HTMLDivElement) => void;
3738
children?: ((instance: Form) => React.ReactNode) | React.ReactNode;
3839
defaultFormValue?: FormValue;
3940
getDefaultFieldValue?: (name: string, formValue: FormValue) => any;
@@ -51,7 +52,7 @@ export interface IFormProps {
5152
prevValue: any,
5253
formValue: FormValue
5354
) => any;
54-
onSubmit?: () => any;
55+
onSubmit?: (e: React.FormEvent) => void;
5556
onChange?: (formValue: FormValue) => void;
5657
getInputProps?: (formItem: FormItem) => Partial<FormItemChildrenProps>;
5758
}
@@ -100,6 +101,8 @@ export class Form extends React.Component<Partial<IFormProps>, IFormState> {
100101
fieldLocks: Record<string, any> = {};
101102
formLockId: number = 1;
102103

104+
_isFormValidating: boolean = false;
105+
103106
fields: FormItem[] = [];
104107
_validateCb: ValueChangeCallback[] = [];
105108

@@ -137,11 +140,12 @@ export class Form extends React.Component<Partial<IFormProps>, IFormState> {
137140
return initialFormValue;
138141
}
139142

140-
reset(cb) {
143+
reset(cb?: ValueChangeCallback) {
141144
const initialFormValue = this.getInitialFormValue();
142145

143146
this.fieldLocks = {};
144147
this.formLockId = 1;
148+
this._isFormValidating = false;
145149
// eslint-disable-next-line
146150
this.state.validatingFields = {};
147151
// eslint-disable-next-line
@@ -159,8 +163,8 @@ export class Form extends React.Component<Partial<IFormProps>, IFormState> {
159163
this.setValues({}, cb);
160164
}
161165

162-
getInitialValue(name) {
163-
let initialValue;
166+
getInitialValue(name: string) {
167+
let initialValue: any;
164168

165169
this.fields.forEach(field => {
166170
if (field.props.name === name) {
@@ -171,7 +175,7 @@ export class Form extends React.Component<Partial<IFormProps>, IFormState> {
171175
return initialValue;
172176
}
173177

174-
resetField(name: string, cb) {
178+
resetField(name: string, cb?: ValueChangeCallback) {
175179
this.cleanError(name);
176180

177181
let initialValue = this.getInitialValue(name);
@@ -194,7 +198,7 @@ export class Form extends React.Component<Partial<IFormProps>, IFormState> {
194198
return this.state.formValue;
195199
}
196200

197-
setValues(obj = {}, cb) {
201+
setValues(obj: FormValue = {}, cb?: ValueChangeCallback) {
198202
const { path2obj, onChange } = this.props;
199203
const formValue = this.state.formValue;
200204

@@ -226,7 +230,7 @@ export class Form extends React.Component<Partial<IFormProps>, IFormState> {
226230
}
227231
}
228232

229-
setFormValue(formValue, cb: ValueChangeCallback) {
233+
setFormValue(formValue: FormValue, cb?: ValueChangeCallback) {
230234
return this.setValues(formValue, cb);
231235
}
232236

@@ -242,7 +246,7 @@ export class Form extends React.Component<Partial<IFormProps>, IFormState> {
242246
: value;
243247
}
244248

245-
setValue(name: string, value: any, cb: ValueChangeCallback) {
249+
setValue(name: string, value: any, cb?: ValueChangeCallback) {
246250
const { path2obj, onChange } = this.props;
247251
const formValue = this.state.formValue;
248252

@@ -275,7 +279,7 @@ export class Form extends React.Component<Partial<IFormProps>, IFormState> {
275279
return this.getValue(name);
276280
}
277281

278-
setFieldValue(name: string, value: any, cb: ValueChangeCallback) {
282+
setFieldValue(name: string, value: any, cb?: ValueChangeCallback) {
279283
return this.setValue(name, value, cb);
280284
}
281285

@@ -391,6 +395,8 @@ export class Form extends React.Component<Partial<IFormProps>, IFormState> {
391395
}
392396

393397
isValidating() {
398+
if (this._isFormValidating) return true;
399+
394400
const validatingFields = this.state.validatingFields;
395401
return Object.keys(validatingFields).some(key => validatingFields[key]);
396402
}
@@ -467,14 +473,15 @@ export class Form extends React.Component<Partial<IFormProps>, IFormState> {
467473

468474
validateField(
469475
name: string,
470-
cb: ValidationCallback | null,
471-
triggerType: TriggerType
476+
cb?: ValidationCallback | null,
477+
triggerType?: TriggerType
472478
) {
473479
const callback = cb || noop;
474-
475480
const { asyncTestDelay } = this.props;
476481
const { formError, validatingFields } = this.state;
477482

483+
if (this._isFormValidating) return;
484+
478485
this.fieldLocks[name] = this.fieldLocks[name] || 1;
479486

480487
const lockId = ++this.fieldLocks[name];
@@ -529,7 +536,7 @@ export class Form extends React.Component<Partial<IFormProps>, IFormState> {
529536
);
530537
}
531538

532-
validate(callback: ValidationCallback, triggerType: TriggerType) {
539+
validate(callback: ValidationCallback) {
533540
callback = typeof callback === "function" ? callback : noop;
534541
const formError = {};
535542
let asyncUpdateTimer: number | null = null;
@@ -543,6 +550,8 @@ export class Form extends React.Component<Partial<IFormProps>, IFormState> {
543550
const allErrors: ValidationError[] = [];
544551
let validCounter = 0;
545552

553+
this._isFormValidating = true;
554+
546555
const updateFormState = () => {
547556
if (lockId !== this.formLockId) return;
548557

@@ -576,6 +585,8 @@ export class Form extends React.Component<Partial<IFormProps>, IFormState> {
576585
return;
577586
}
578587

588+
this._isFormValidating = false;
589+
579590
this.setState(
580591
{
581592
formError,
@@ -597,10 +608,6 @@ export class Form extends React.Component<Partial<IFormProps>, IFormState> {
597608
const name = field.props.name;
598609
validCounter++;
599610
validatingFields[name] = true;
600-
601-
// if (!(name in formError)) {
602-
// formError[name] = null;
603-
// }
604611
});
605612

606613
//开始进行字段校验
@@ -614,25 +621,21 @@ export class Form extends React.Component<Partial<IFormProps>, IFormState> {
614621
asyncTimer = null;
615622
}, asyncTestDelay) as unknown) as number;
616623

617-
this._validateField(
618-
name,
619-
errors => {
620-
validatingFields[name] = false;
624+
this._validateField(name, errors => {
625+
validatingFields[name] = false;
621626

622-
if (asyncTimer) {
623-
clearTimeout(asyncTimer);
624-
asyncTimer = null;
625-
}
627+
if (asyncTimer) {
628+
clearTimeout(asyncTimer);
629+
asyncTimer = null;
630+
}
626631

627-
//异步校验完成后执行刷新动作
628-
if (isAsyncValidate) {
629-
updateFormState();
630-
}
632+
//异步校验完成后执行刷新动作
633+
if (isAsyncValidate) {
634+
updateFormState();
635+
}
631636

632-
complete(errors, name);
633-
},
634-
triggerType
635-
);
637+
complete(errors, name);
638+
});
636639
});
637640

638641
//如果校验方法中存在异步校验则先显示同步校验的信息及异步状态
@@ -647,8 +650,9 @@ export class Form extends React.Component<Partial<IFormProps>, IFormState> {
647650
}
648651
}
649652

650-
validateAndScroll(callback, triggerType) {
651-
callback = typeof callback === "function" ? callback : noop;
653+
validateAndScroll(cb?: ValidationCallback) {
654+
const { scrollIntoView } = this.props;
655+
const callback = typeof cb === "function" ? cb : noop;
652656

653657
this.validate((errors, formValue, isAbort) => {
654658
if (errors) {
@@ -658,7 +662,11 @@ export class Form extends React.Component<Partial<IFormProps>, IFormState> {
658662
const name = field.props.name;
659663
if (this.hasError(name)) {
660664
const dom = field.getDOM();
661-
if (dom && dom.scrollIntoView) {
665+
666+
if (scrollIntoView) {
667+
scrollIntoView(dom);
668+
break;
669+
} else if (dom && dom.scrollIntoView) {
662670
dom.scrollIntoView();
663671
break;
664672
}
@@ -667,7 +675,7 @@ export class Form extends React.Component<Partial<IFormProps>, IFormState> {
667675
}
668676

669677
callback(errors, formValue, isAbort);
670-
}, triggerType);
678+
});
671679
}
672680

673681
getFormContext(this: Form) {

src/FormItem.tsx

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { IFormProps } from "./Form";
88
import {
99
FormValue,
1010
TriggerType,
11-
ValidationError,
11+
ValidateTrigger,
1212
ValueChangeCallback,
1313
ValidationCallback,
1414
Validator,
@@ -40,32 +40,28 @@ export interface IFormItemProps {
4040
props: FormItemChildrenProps,
4141
instance: FormItem
4242
) => React.ReactNode)
43-
| React.ReactNode; //PropTypes.oneOfType([PropTypes.func, PropTypes.node]).isRequired,
43+
| React.ReactNode;
4444

4545
style?: React.CSSProperties;
4646
className?: string;
4747
disableValidator?: boolean;
4848
label?: React.ReactNode;
49-
labelFor?: string; //PropTypes.oneOfType([string PropTypes.number]),
50-
labelWidth?: string | number; //PropTypes.oneOfType([string PropTypes.number]),
49+
labelFor?: string;
50+
labelWidth?: number;
5151
labelStyle?: React.CSSProperties;
5252
labelClassName?: string;
53-
labelPosition?: "top" | "left"; //PropTypes.oneOf(["top", "left"]),
54-
labelAlign?: "left" | "right"; //PropTypes.oneOf(["left", "right"]),
55-
controlStyle?: {};
53+
labelPosition?: "top" | "left";
54+
labelAlign?: "left" | "right";
55+
controlStyle?: React.CSSProperties;
5656
controlClassName?: string;
57-
validator?: () => boolean; //PropTypes.oneOfType([PropTypes.func, PropTypes.array]),
57+
validator?: Validator | Validator[];
5858

5959
required?: boolean;
6060
requiredMessage?: string;
6161
clearErrorOnFocus?: boolean;
6262
normalize?: (value: any, prevValue: any, formValue: FormValue) => any;
6363
renderExtra?: (instance: FormItem) => React.ReactNode;
64-
validateTrigger?:
65-
| "blur"
66-
| "change"
67-
| "none"
68-
| ("blur" | "change" | "none")[]; // onBlur onChange
64+
validateTrigger?: ValidateTrigger;
6965
inline?: boolean;
7066
renderControlExtra?: () => React.ReactNode;
7167
onChange?: (value: any) => void;
@@ -114,13 +110,6 @@ export class FormItem extends React.Component<Partial<IFormItemProps>> {
114110
return this._initialValue;
115111
}
116112

117-
// getInitialValue() {
118-
// const { name } = this.props;
119-
// const form = this.getForm();
120-
121-
// return form.getInitialValue(name);
122-
// }
123-
124113
saveDOM = (dom: HTMLDivElement) => {
125114
this._dom = dom;
126115
};
@@ -198,7 +187,7 @@ export class FormItem extends React.Component<Partial<IFormItemProps>> {
198187
}
199188

200189
validate(
201-
callback: ValidationCallback | null,
190+
callback?: ValidationCallback | null,
202191
triggerType: TriggerType = "none"
203192
) {
204193
const form = this.getForm();
@@ -214,7 +203,7 @@ export class FormItem extends React.Component<Partial<IFormItemProps>> {
214203
return form.getValue(name);
215204
}
216205

217-
setValue(value: any, callback: ValueChangeCallback) {
206+
setValue(value: any, callback?: ValueChangeCallback) {
218207
const form = this.getForm();
219208
const { name } = this.props;
220209

@@ -234,7 +223,7 @@ export class FormItem extends React.Component<Partial<IFormItemProps>> {
234223
}
235224
}
236225

237-
handleChange = (value, callback) => {
226+
handleChange = (value: any, callback?: () => void) => {
238227
this.setValue(value, formValue => {
239228
callback && callback();
240229

src/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export type ValueChangeCallback = (fromValue: FormValue) => void;
1111
export type ValidationCallback = (
1212
errors: ValidationError[] | null,
1313
value: any,
14-
state?: boolean
14+
isAbort?: boolean
1515
) => void;
1616

1717
export type Validator = (

src/utils.ts

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,3 @@ export function isEmptyValue<T>(value: T) {
1111

1212
return false;
1313
}
14-
15-
// export function deferred() {
16-
// const deferred = {};
17-
18-
// deferred.promise = new Promise((resolve, reject) => {
19-
// deferred.resolve = resolve;
20-
// deferred.reject = reject;
21-
// });
22-
23-
// return deferred;
24-
// }

0 commit comments

Comments
 (0)