Skip to content

Commit

Permalink
perf: improve total performance 20% (#2589)
Browse files Browse the repository at this point in the history
  • Loading branch information
janryWang authored Dec 7, 2021
1 parent 5befbad commit 2d98138
Show file tree
Hide file tree
Showing 21 changed files with 222 additions and 225 deletions.
79 changes: 34 additions & 45 deletions packages/antd/src/form-item/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -361,60 +361,49 @@ export const BaseItem: React.FC<IFormItemProps> = ({ children, ...props }) => {
// 适配
export const FormItem: ComposeFormItem = connect(
BaseItem,
mapProps(
{ validateStatus: true, title: 'label', required: true },
(props, field) => {
if (isVoidField(field))
return {
extra: props.extra || field.description,
}
if (!field) return props
const takeMessage = () => {
const split = (messages: any[]) => {
return messages.reduce((buf, text, index) => {
if (!text) return buf
return index < messages.length - 1
? buf.concat([text, ', '])
: buf.concat([text])
}, [])
}
if (field.validating) return
if (props.feedbackText) return props.feedbackText
if (field.selfErrors.length) return split(field.selfErrors)
if (field.selfWarnings.length) return split(field.selfWarnings)
if (field.selfSuccesses.length) return split(field.selfSuccesses)
}

mapProps((props, field) => {
if (isVoidField(field))
return {
feedbackText: takeMessage(),
extra: props.extra || field.description,
}
},
(props, field) => {
if (isVoidField(field)) return props
if (!field) return props
return {
feedbackStatus:
field.validateStatus === 'validating'
? 'pending'
: field.decorator[1]?.feedbackStatus || field.validateStatus,
if (!field) return props
const takeFeedbackStatus = () => {
if (!field.selfModified) return
if (field.validating) return 'pending'
return field.decoratorProps.feedbackStatus || field.validateStatus
}
const takeMessage = () => {
const split = (messages: any[]) => {
return messages.reduce((buf, text, index) => {
if (!text) return buf
return index < messages.length - 1
? buf.concat([text, ', '])
: buf.concat([text])
}, [])
}
},
(props, field) => {
if (isVoidField(field)) return props
if (!field) return props
let asterisk = false
if (field.validating || !field.selfModified) return
if (props.feedbackText) return props.feedbackText
if (field.selfErrors.length) return split(field.selfErrors)
if (field.selfWarnings.length) return split(field.selfWarnings)
if (field.selfSuccesses.length) return split(field.selfSuccesses)
}
const takeAsterisk = () => {
if (field.required && field.pattern !== 'readPretty') {
asterisk = true
return true
}
if ('asterisk' in props) {
asterisk = props.asterisk
}
return {
asterisk,
return props.asterisk
}
return false
}
)
return {
label: field.title,
feedbackStatus: takeFeedbackStatus(),
feedbackText: takeMessage(),
asterisk: takeAsterisk(),
extra: props.extra || field.description,
}
})
)

FormItem.BaseItem = BaseItem
Expand Down
22 changes: 17 additions & 5 deletions packages/antd/src/form-layout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,21 @@ export interface IFormLayoutProps {
gridRowGap?: number
}

export const FormLayoutDeepContext = createContext<IFormLayoutProps>(null)
export interface IFormLayoutContext
extends Omit<
IFormLayoutProps,
'labelAlign' | 'wrapperAlign' | 'layout' | 'labelCol' | 'wrapperCol'
> {
labelAlign?: 'right' | 'left'
wrapperAlign?: 'right' | 'left'
layout?: 'vertical' | 'horizontal' | 'inline'
labelCol?: number
wrapperCol?: number
}

export const FormLayoutDeepContext = createContext<IFormLayoutContext>(null)

export const FormLayoutShallowContext = createContext<IFormLayoutProps>(null)
export const FormLayoutShallowContext = createContext<IFormLayoutContext>(null)

export const useFormDeepLayout = () => useContext(FormLayoutDeepContext)

Expand All @@ -50,9 +62,9 @@ export const useFormLayout = () => ({
})

export const FormLayout: React.FC<IFormLayoutProps> & {
useFormLayout: () => IFormLayoutProps
useFormDeepLayout: () => IFormLayoutProps
useFormShallowLayout: () => IFormLayoutProps
useFormLayout: () => IFormLayoutContext
useFormDeepLayout: () => IFormLayoutContext
useFormShallowLayout: () => IFormLayoutContext
} = ({ shallow, children, prefixCls, className, style, ...otherProps }) => {
const { ref, props } = useResponsiveFormLayout(otherProps)
const deepLayout = useFormDeepLayout()
Expand Down
4 changes: 2 additions & 2 deletions packages/antd/src/form-layout/useResponsiveFormLayout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ interface ICalculateProps {
interface IUseResponsiveFormLayout {
(props: IProps): {
ref: React.MutableRefObject<HTMLDivElement>
props: IProps
props: any
}
}

Expand Down Expand Up @@ -79,7 +79,7 @@ export const useResponsiveFormLayout: IUseResponsiveFormLayout = (props) => {
if (!isArr(breakpoints)) {
return { ref, props }
}
const [layoutProps, setLayout] = useState<IProps>(props)
const [layoutProps, setLayout] = useState<any>(props)

const updateUI = () => {
setLayout(calculateProps(ref.current, props))
Expand Down
8 changes: 4 additions & 4 deletions packages/core/src/__tests__/field.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -544,11 +544,11 @@ test('setValidateRule', () => {
field5.setValidatorRule('min', 3)
field6.setValidatorRule('min', 3)
expect(field1.validator).toEqual([{ required: true }, { format: 'phone' }])
expect(field2.validator).toEqual(['phone', { max: 3 }])
expect(field3.validator).toEqual({ format: 'url' })
expect(field4.validator).toEqual({ format: 'phone', min: 3 })
expect(field2.validator).toEqual([{ format: 'phone' }, { max: 3 }])
expect(field3.validator).toEqual([{ format: 'url' }])
expect(field4.validator).toEqual([{ format: 'phone' }, { min: 3 }])
expect(field5.validator).toEqual([{ format: 'phone' }, { min: 3 }])
expect(field6.validator).toEqual({ min: 3 })
expect(field6.validator).toEqual([{ min: 3 }])
})

test('query', () => {
Expand Down
15 changes: 11 additions & 4 deletions packages/core/src/models/Field.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { isValid, isEmpty, toArr, FormPathPattern } from '@formily/shared'
import {
isValid,
isEmpty,
toArr,
FormPathPattern,
isArr,
} from '@formily/shared'
import {
ValidatorTriggerType,
parseValidatorDescriptions,
Expand Down Expand Up @@ -329,9 +335,10 @@ export class Field<
}

get required() {
return parseValidatorDescriptions(this.validator).some(
(desc) => desc.required
)
const validators = isArr(this.validator)
? this.validator
: parseValidatorDescriptions(this.validator)
return validators.some((desc) => !!desc?.['required'])
}

get validateStatus() {
Expand Down
44 changes: 11 additions & 33 deletions packages/core/src/shared/internals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
isFn,
isValid,
isEmpty,
isArr,
isPlainObj,
isNumberLike,
clone,
Expand Down Expand Up @@ -274,7 +273,7 @@ export const updateFeedback = (field: Field, feedback?: IFieldFeedback) => {

export const validateToFeedbacks = async (
field: Field,
triggerType?: ValidatorTriggerType
triggerType: ValidatorTriggerType = 'onInput'
) => {
const results = await validate(field.value, field.validator, {
triggerType,
Expand All @@ -297,45 +296,24 @@ export const validateToFeedbacks = async (

export const setValidatorRule = (field: Field, name: string, value: any) => {
if (!isValid(value)) return
const hasRule = parseValidatorDescriptions(field.validator).some(
(desc) => name in desc
)
const validators = parseValidatorDescriptions(field.validator)
const hasRule = validators.some((desc) => name in desc)
const rule = {
[name]: value,
}
if (hasRule) {
if (isArr(field.validator)) {
field.validator = field.validator.map((desc: any) => {
if (isPlainObj(desc) && hasOwnProperty.call(desc, name)) {
desc[name] = value
return desc
}
field.validator = validators.map((desc: any) => {
if (isPlainObj(desc) && hasOwnProperty.call(desc, name)) {
desc[name] = value
return desc
})
} else if (isPlainObj(field.validator)) {
field.validator[name] = value
} else {
field.validator = {
[name]: value,
}
}
return desc
})
} else {
if (isArr(field.validator)) {
if (name === 'required') {
field.validator.unshift(rule)
} else {
field.validator.push(rule)
}
if (name === 'required') {
field.validator = [rule].concat(validators)
} else {
if (name === 'required') {
field.validator = [rule, field.validator]
} else if (isPlainObj(field.validator)) {
field.validator[name] = value
} else if (field.validator) {
field.validator = [field.validator, rule]
} else {
field.validator = rule
}
field.validator = validators.concat(rule)
}
}
}
Expand Down
79 changes: 34 additions & 45 deletions packages/next/src/form-item/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -364,60 +364,49 @@ export const BaseItem: React.FC<IFormItemProps> = (props) => {
// 适配
export const FormItem: ComposeFormItem = connect(
BaseItem,
mapProps(
{ validateStatus: true, title: 'label', required: true },
(props, field) => {
if (isVoidField(field))
return {
extra: props.extra || field.description,
}
if (!field) return props
const takeMessage = () => {
const split = (messages: any[]) => {
return messages.reduce((buf, text, index) => {
if (!text) return buf
return index < messages.length - 1
? buf.concat([text, ', '])
: buf.concat([text])
}, [])
}
if (field.validating) return
if (props.feedbackText) return props.feedbackText
if (field.selfErrors.length) return split(field.selfErrors)
if (field.selfWarnings.length) return split(field.selfWarnings)
if (field.selfSuccesses.length) return split(field.selfSuccesses)
}

mapProps((props, field) => {
if (isVoidField(field))
return {
feedbackText: takeMessage(),
extra: props.extra || field.description,
}
},
(props, field) => {
if (isVoidField(field)) return props
if (!field) return props
return {
feedbackStatus:
field.validateStatus === 'validating'
? 'pending'
: field.decorator[1]?.feedbackStatus || field.validateStatus,
if (!field) return props
const takeFeedbackStatus = () => {
if (!field.selfModified) return
if (field.validating) return 'pending'
return field.decoratorProps.feedbackStatus || field.validateStatus
}
const takeMessage = () => {
const split = (messages: any[]) => {
return messages.reduce((buf, text, index) => {
if (!text) return buf
return index < messages.length - 1
? buf.concat([text, ', '])
: buf.concat([text])
}, [])
}
},
(props, field) => {
if (isVoidField(field)) return props
if (!field) return props
let asterisk = false
if (field.validating || !field.selfModified) return
if (props.feedbackText) return props.feedbackText
if (field.selfErrors.length) return split(field.selfErrors)
if (field.selfWarnings.length) return split(field.selfWarnings)
if (field.selfSuccesses.length) return split(field.selfSuccesses)
}
const takeAsterisk = () => {
if (field.required && field.pattern !== 'readPretty') {
asterisk = true
return true
}
if ('asterisk' in props) {
asterisk = props.asterisk
}
return {
asterisk,
return props.asterisk
}
return false
}
)
return {
label: field.title,
feedbackStatus: takeFeedbackStatus(),
feedbackText: takeMessage(),
asterisk: takeAsterisk(),
extra: props.extra || field.description,
}
})
)

FormItem.defaultProps = {
Expand Down
22 changes: 17 additions & 5 deletions packages/next/src/form-layout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,21 @@ export interface IFormLayoutProps {
spaceGap?: number
}

export const FormLayoutDeepContext = createContext<IFormLayoutProps>(null)
export interface IFormLayoutContext
extends Omit<
IFormLayoutProps,
'labelAlign' | 'wrapperAlign' | 'layout' | 'labelCol' | 'wrapperCol'
> {
labelAlign?: 'right' | 'left'
wrapperAlign?: 'right' | 'left'
layout?: 'vertical' | 'horizontal' | 'inline'
labelCol?: number
wrapperCol?: number
}

export const FormLayoutDeepContext = createContext<IFormLayoutContext>(null)

export const FormLayoutShallowContext = createContext<IFormLayoutProps>(null)
export const FormLayoutShallowContext = createContext<IFormLayoutContext>(null)

export const useFormDeepLayout = () => useContext(FormLayoutDeepContext)

Expand All @@ -50,9 +62,9 @@ export const useFormLayout = () => ({
})

export const FormLayout: React.FC<IFormLayoutProps> & {
useFormLayout: () => IFormLayoutProps
useFormDeepLayout: () => IFormLayoutProps
useFormShallowLayout: () => IFormLayoutProps
useFormLayout: () => IFormLayoutContext
useFormDeepLayout: () => IFormLayoutContext
useFormShallowLayout: () => IFormLayoutContext
} = ({ shallow, children, prefix, className, style, ...otherProps }) => {
const { ref, props } = useResponsiveFormLayout(otherProps)
const deepLayout = useFormDeepLayout()
Expand Down
Loading

0 comments on commit 2d98138

Please sign in to comment.