5 changed files with 221 additions and 11 deletions
@ -0,0 +1,154 @@ |
|||
import { flushPromises, mount } from '@vue/test-utils'; |
|||
import { defineComponent, h, nextTick } from 'vue'; |
|||
|
|||
import { afterAll, bench, describe } from 'vitest'; |
|||
|
|||
import { setupVbenForm } from '../src/config'; |
|||
import { FormApi } from '../src/form-api'; |
|||
import { encodeFormValues } from '../src/form-codec'; |
|||
import { useVbenForm } from '../src/use-vben-form'; |
|||
|
|||
interface ContactValues { |
|||
enabled: boolean; |
|||
metadata: { |
|||
permissions: string[]; |
|||
team: string; |
|||
}; |
|||
name: string; |
|||
phone: string; |
|||
tags: string[]; |
|||
} |
|||
|
|||
interface PerformanceFormValues extends Record<string, unknown> { |
|||
contacts: ContactValues[]; |
|||
settings: { |
|||
alerts: boolean; |
|||
locale: string; |
|||
sections: string[]; |
|||
}; |
|||
} |
|||
|
|||
const ROW_COUNT = 100; |
|||
|
|||
const TestInput = defineComponent({ |
|||
inheritAttrs: false, |
|||
emits: ['update:modelValue'], |
|||
setup(_props, { attrs, emit }) { |
|||
function handleInput(event: Event) { |
|||
const target = event.target; |
|||
if (target instanceof HTMLInputElement) { |
|||
emit('update:modelValue', target.value); |
|||
} |
|||
} |
|||
|
|||
return () => |
|||
h('input', { |
|||
...attrs, |
|||
onInput: handleInput, |
|||
value: attrs.modelValue ?? '', |
|||
}); |
|||
}, |
|||
}); |
|||
|
|||
function createFormValues(): PerformanceFormValues { |
|||
return { |
|||
contacts: Array.from({ length: ROW_COUNT }, (_, index) => ({ |
|||
enabled: index % 2 === 0, |
|||
metadata: { |
|||
permissions: ['read', 'write', 'review'], |
|||
team: `team-${index % 10}`, |
|||
}, |
|||
name: ` Contact ${index} `, |
|||
phone: `10086-${index}`, |
|||
tags: ['primary', 'on-call', `group-${index % 5}`], |
|||
})), |
|||
settings: { |
|||
alerts: true, |
|||
locale: 'zh-CN', |
|||
sections: ['profile', 'security', 'notifications'], |
|||
}, |
|||
}; |
|||
} |
|||
|
|||
const codec = { |
|||
decode: (values: Readonly<PerformanceFormValues>) => ({ ...values }), |
|||
encode: (values: Readonly<PerformanceFormValues>) => ({ |
|||
...values, |
|||
contacts: values.contacts.map((contact) => ({ |
|||
...contact, |
|||
name: contact.name.trim(), |
|||
})), |
|||
}), |
|||
}; |
|||
|
|||
const formValues = createFormValues(); |
|||
const codecFormApi = new FormApi<PerformanceFormValues>({ codec }); |
|||
codecFormApi.mount({ meta: {}, values: formValues } as never, new Map()); |
|||
|
|||
setupVbenForm({ config: {}, rules: {} }); |
|||
const [ArrayForm, arrayFormApi] = useVbenForm({ |
|||
schema: [ |
|||
{ |
|||
children: [ |
|||
{ |
|||
component: TestInput, |
|||
fieldName: 'name', |
|||
label: 'Name', |
|||
}, |
|||
], |
|||
defaultValue: Array.from({ length: ROW_COUNT }, (_, index) => ({ |
|||
name: `Contact ${index}`, |
|||
})), |
|||
fieldName: 'contacts', |
|||
type: 'array', |
|||
}, |
|||
], |
|||
}); |
|||
const arrayWrapper = mount(ArrayForm); |
|||
await flushPromises(); |
|||
let arrayEditIteration = 0; |
|||
|
|||
afterAll(() => { |
|||
arrayWrapper.unmount(); |
|||
}); |
|||
|
|||
describe('form codec performance', () => { |
|||
bench( |
|||
'encode 100 nested rows without isolation', |
|||
() => { |
|||
encodeFormValues(codec, formValues); |
|||
}, |
|||
{ time: 1000, warmupTime: 200 }, |
|||
); |
|||
|
|||
bench( |
|||
'encode 100 nested rows with isolated input', |
|||
() => { |
|||
codecFormApi.formatValues(formValues); |
|||
}, |
|||
{ time: 1000, warmupTime: 200 }, |
|||
); |
|||
|
|||
bench( |
|||
'create submit snapshot for 100 nested rows', |
|||
async () => { |
|||
await codecFormApi.getValueSnapshot(); |
|||
}, |
|||
{ time: 1000, warmupTime: 200 }, |
|||
); |
|||
}); |
|||
|
|||
describe('form array performance', () => { |
|||
bench( |
|||
'edit one field in a 100-row array', |
|||
async () => { |
|||
arrayEditIteration += 1; |
|||
await arrayFormApi.setFieldValue( |
|||
'contacts[50].name', |
|||
`Contact ${arrayEditIteration}`, |
|||
); |
|||
await nextTick(); |
|||
}, |
|||
{ time: 1000, warmupTime: 200 }, |
|||
); |
|||
}); |
|||
Loading…
Reference in new issue