feat: 更新 PSelect 组件,支持异步选项加载并优化 blur 事件处理
All checks were successful
/ test (push) Successful in 20s
/ surge (push) Successful in 48s

This commit is contained in:
严浩
2024-12-06 13:13:24 +08:00
parent 603c1047fc
commit 7b7828d384
3 changed files with 81 additions and 42 deletions

View File

@ -6,6 +6,9 @@
- [sections](https://formkit.com/inputs/text#sections) - [sections](https://formkit.com/inputs/text#sections)
- [sections](https://formkit.com/essentials/inputs#sections) - [sections](https://formkit.com/essentials/inputs#sections)
- [useformkitcontext](https://formkit.com/inputs/form#useformkitcontext) - [useformkitcontext](https://formkit.com/inputs/form#useformkitcontext)
- [debouncing](https://formkit.com/essentials/inputs#debouncing)
延迟 prop 的默认值是 20 毫秒。然而group 和 list 输入默认使用 0 毫秒,以防止防抖延迟在每个深度级别“累积”。
## Custom Input ## Custom Input

View File

@ -2,7 +2,7 @@ import type { FormKitFrameworkContext, FormKitTypeDefinition } from '@formkit/co
import type { FormKitInputs } from '@formkit/inputs'; import type { FormKitInputs } from '@formkit/inputs';
import { createSection, label, outer } from '@formkit/inputs'; import { createSection, label, outer } from '@formkit/inputs';
import PrimevueSelect, { type SelectEmitsOptions } from 'primevue/select'; import PrimevueSelect, { type SelectEmitsOptions } from 'primevue/select';
import { defineComponent, markRaw } from 'vue'; import { defineComponent, markRaw, ref } from 'vue';
import { floatLabel } from '../sections/floatLabel'; import { floatLabel } from '../sections/floatLabel';
import { messages } from '../sections/messages'; import { messages } from '../sections/messages';
@ -21,14 +21,23 @@ const PSelectComp = defineComponent(
formkitContext.node.input(value); formkitContext.node.input(value);
}, },
'onBlur': async e => { 'onBlur': async e => {
setTimeout(() => formkitContext.handlers.blur.call(undefined, e as never), 20); setTimeout(
() => formkitContext.handlers.blur.call(undefined, e as never),
166, // 因为会触发两次。所以让blur事件延迟一点可以考虑优化。
);
}, },
/* https://formkit.com/essentials/inputs#debouncing
* The default debounce delay is 20 milliseconds and can be adjusted with the delay prop or config option.
* 延迟 prop 的默认值是 20 毫秒。然而group 和 list 输入默认使用 0 毫秒,以防止防抖延迟在每个深度级别“累积”。
* 不过好像不是这个造成的`blur`比`change`先触发。
*/
}; };
const poptions = ref();
const loading = ref(true);
if (formkitContext.options instanceof Promise) {
formkitContext.options.then((res: any) => {
poptions.value = res;
loading.value = false;
});
} else {
poptions.value = formkitContext.options;
loading.value = false;
}
return () => { return () => {
return ( return (
@ -37,8 +46,11 @@ const PSelectComp = defineComponent(
fluid fluid
invalid={formkitContext.state.invalid} invalid={formkitContext.state.invalid}
disabled={!!formkitContext.disabled} disabled={!!formkitContext.disabled}
options={formkitContext.options} loading={loading.value}
options={poptions.value}
modelValue={formkitContext._value} modelValue={formkitContext._value}
optionLabel={formkitContext.optionLabel as never}
optionValue={formkitContext.optionValue as never}
{...listeners} {...listeners}
/> />
); );
@ -69,16 +81,19 @@ export const PSelect: FormKitTypeDefinition = {
), ),
messages(), messages(),
), ),
props: ['options'], props: ['options', 'optionLabel', 'optionValue'],
// schemaMemoKey: 'nnvujvlf2xr', // Math.random().toString(36).substring(2, 15) // schemaMemoKey: 'nnvujvlf2xr', // Math.random().toString(36).substring(2, 15)
}; };
type OptionsItem = Record<string, any>;
type OptionsType = Array<OptionsItem>;
declare module '@formkit/inputs' { declare module '@formkit/inputs' {
// https://formkit.com/essentials/custom-inputs#typescript-support // https://formkit.com/essentials/custom-inputs#typescript-support
interface FormKitInputProps<Props extends FormKitInputs<Props>> { interface FormKitInputProps<Props extends FormKitInputs<Props>> {
PSelect: { PSelect: {
type: 'PSelect'; type: 'PSelect';
options: any; options: OptionsType | Promise<OptionsType>;
}; };
} }
} }

View File

@ -17,6 +17,19 @@ async function submit(formData: Record<string, any>, formNode: FormKitNode) {
timer: 1500 timer: 1500
}) })
} }
const K_OPTIONS = [
{ label: 'Option 1', value: 'Value 1' },
{ label: 'Option 2', value: 'Value 2' },
{ label: 'Option 3', value: 'Value 3' },
];
const promiseOptions = () => {
return new Promise<typeof K_OPTIONS>(resolve => {
setTimeout(() => {
resolve(K_OPTIONS);
}, 1000);
});
};
</script> </script>
<template> <template>
@ -71,47 +84,55 @@ async function submit(formData: Record<string, any>, formNode: FormKitNode) {
name="PSelect" name="PSelect"
label="选择框" label="选择框"
validation="required" validation="required"
:options="[ :options="K_OPTIONS"
'Option 1', optionLabel="label"
'Option 2', optionValue="value"
'Option 3',
]"
valuee="Option 2"
/> />
<FormKit <FormKit
v-if="!value?.PInputPassword" type="PSelect"
:type="text" name="PSelect"
:preserve="false" label="选择框"
name="customType" validation="required"
value="this input will display if the password is empty" :options="promiseOptions()"
> optionLabel="label"
<!-- <template #label> optionValue="value"
/>
<div class="flex gap-4">
<FormKit
v-if="!value?.PInputPassword"
:type="text"
:preserve="false"
name="customType"
value="this input will display if the password is empty"
>
<!-- <template #label>
<div>labelll</div> <div>labelll</div>
</template> --> </template> -->
</FormKit>
<FormKit
type="group"
name="group"
>
<FormKit
type="text"
name="text-in-group-1"
>
</FormKit> </FormKit>
</FormKit>
<FormKit
type="group"
name="group"
>
<FormKit <FormKit
type="text" type="group"
name="text-in-group-2" name="group"
> >
<FormKit
type="text"
name="text-in-group-1"
>
</FormKit>
</FormKit> </FormKit>
</FormKit>
<FormKit
type="group"
name="group"
>
<FormKit
type="text"
name="text-in-group-2"
>
</FormKit>
</FormKit>
</div>
<Button <Button
label="Button" label="Button"