perf: improve component packaging to enable instance method retrieval (#5795)

改进组件适配器里的包装函数,使得组件暴露的方法可以透传
This commit is contained in:
Netfan 2025-03-27 15:13:13 +08:00 committed by GitHub
parent 870cd86393
commit a77bb8e68d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 97 additions and 176 deletions

View File

@ -41,6 +41,7 @@ import {
const withDefaultPlaceholder = <T extends Component>( const withDefaultPlaceholder = <T extends Component>(
component: T, component: T,
type: 'input' | 'select', type: 'input' | 'select',
componentProps: Recordable<any> = {},
) => { ) => {
return defineComponent({ return defineComponent({
inheritAttrs: false, inheritAttrs: false,
@ -63,7 +64,11 @@ const withDefaultPlaceholder = <T extends Component>(
} }
}); });
return () => return () =>
h(component, { ...props, ...attrs, placeholder, ref: innerRef }, slots); h(
component,
{ ...componentProps, placeholder, ...props, ...attrs, ref: innerRef },
slots,
);
}, },
}); });
}; };
@ -102,38 +107,20 @@ async function initComponentAdapter() {
// 如果你的组件体积比较大,可以使用异步加载 // 如果你的组件体积比较大,可以使用异步加载
// Button: () => // Button: () =>
// import('xxx').then((res) => res.Button), // import('xxx').then((res) => res.Button),
ApiSelect: (props, { attrs, slots }) => { ApiSelect: withDefaultPlaceholder(ApiComponent, 'select', {
return h( component: Select,
ApiComponent, loadingSlot: 'suffixIcon',
{ visibleEvent: 'onDropdownVisibleChange',
placeholder: $t('ui.placeholder.select'), modelPropName: 'value',
...props, }),
...attrs, ApiTreeSelect: withDefaultPlaceholder(ApiComponent, 'select', {
component: Select, component: TreeSelect,
loadingSlot: 'suffixIcon', fieldNames: { label: 'label', value: 'value', children: 'children' },
visibleEvent: 'onDropdownVisibleChange', loadingSlot: 'suffixIcon',
modelPropName: 'value', modelPropName: 'value',
}, optionsPropName: 'treeData',
slots, visibleEvent: 'onVisibleChange',
); }),
},
ApiTreeSelect: (props, { attrs, slots }) => {
return h(
ApiComponent,
{
placeholder: $t('ui.placeholder.select'),
...props,
...attrs,
component: TreeSelect,
fieldNames: { label: 'label', value: 'value', children: 'children' },
loadingSlot: 'suffixIcon',
modelPropName: 'value',
optionsPropName: 'treeData',
visibleEvent: 'onVisibleChange',
},
slots,
);
},
AutoComplete, AutoComplete,
Checkbox, Checkbox,
CheckboxGroup, CheckboxGroup,
@ -143,19 +130,11 @@ async function initComponentAdapter() {
return h(Button, { ...props, attrs, type: 'default' }, slots); return h(Button, { ...props, attrs, type: 'default' }, slots);
}, },
Divider, Divider,
IconPicker: (props, { attrs, slots }) => { IconPicker: withDefaultPlaceholder(IconPicker, 'select', {
return h( iconSlot: 'addonAfter',
IconPicker, inputComponent: Input,
{ modelValueProp: 'value',
iconSlot: 'addonAfter', }),
inputComponent: Input,
modelValueProp: 'value',
...props,
...attrs,
},
slots,
);
},
Input: withDefaultPlaceholder(Input, 'input'), Input: withDefaultPlaceholder(Input, 'input'),
InputNumber: withDefaultPlaceholder(InputNumber, 'input'), InputNumber: withDefaultPlaceholder(InputNumber, 'input'),
InputPassword: withDefaultPlaceholder(InputPassword, 'input'), InputPassword: withDefaultPlaceholder(InputPassword, 'input'),

View File

@ -37,6 +37,7 @@ import {
const withDefaultPlaceholder = <T extends Component>( const withDefaultPlaceholder = <T extends Component>(
component: T, component: T,
type: 'input' | 'select', type: 'input' | 'select',
componentProps: Recordable<any> = {},
) => { ) => {
return defineComponent({ return defineComponent({
inheritAttrs: false, inheritAttrs: false,
@ -59,7 +60,11 @@ const withDefaultPlaceholder = <T extends Component>(
} }
}); });
return () => return () =>
h(component, { ...props, ...attrs, placeholder, ref: innerRef }, slots); h(
component,
{ ...componentProps, placeholder, ...props, ...attrs, ref: innerRef },
slots,
);
}, },
}); });
}; };
@ -89,37 +94,19 @@ async function initComponentAdapter() {
// 如果你的组件体积比较大,可以使用异步加载 // 如果你的组件体积比较大,可以使用异步加载
// Button: () => // Button: () =>
// import('xxx').then((res) => res.Button), // import('xxx').then((res) => res.Button),
ApiSelect: (props, { attrs, slots }) => { ApiSelect: withDefaultPlaceholder(ApiComponent, 'select', {
return h( component: ElSelectV2,
ApiComponent, loadingSlot: 'loading',
{ visibleEvent: 'onVisibleChange',
placeholder: $t('ui.placeholder.select'), }),
...props, ApiTreeSelect: withDefaultPlaceholder(ApiComponent, 'select', {
...attrs, component: ElTreeSelect,
component: ElSelectV2, props: { label: 'label', children: 'children' },
loadingSlot: 'loading', nodeKey: 'value',
visibleEvent: 'onVisibleChange', loadingSlot: 'loading',
}, optionsPropName: 'data',
slots, visibleEvent: 'onVisibleChange',
); }),
},
ApiTreeSelect: (props, { attrs, slots }) => {
return h(
ApiComponent,
{
placeholder: $t('ui.placeholder.select'),
...props,
...attrs,
component: ElTreeSelect,
props: { label: 'label', children: 'children' },
nodeKey: 'value',
loadingSlot: 'loading',
optionsPropName: 'data',
visibleEvent: 'onVisibleChange',
},
slots,
);
},
Checkbox: ElCheckbox, Checkbox: ElCheckbox,
CheckboxGroup: (props, { attrs, slots }) => { CheckboxGroup: (props, { attrs, slots }) => {
let defaultSlot; let defaultSlot;
@ -149,19 +136,11 @@ async function initComponentAdapter() {
return h(ElButton, { ...props, attrs, type: 'primary' }, slots); return h(ElButton, { ...props, attrs, type: 'primary' }, slots);
}, },
Divider: ElDivider, Divider: ElDivider,
IconPicker: (props, { attrs, slots }) => { IconPicker: withDefaultPlaceholder(IconPicker, 'select', {
return h( iconSlot: 'append',
IconPicker, modelValueProp: 'model-value',
{ inputComponent: ElInput,
iconSlot: 'append', }),
modelValueProp: 'model-value',
inputComponent: ElInput,
...props,
...attrs,
},
slots,
);
},
Input: withDefaultPlaceholder(ElInput, 'input'), Input: withDefaultPlaceholder(ElInput, 'input'),
InputNumber: withDefaultPlaceholder(ElInputNumber, 'input'), InputNumber: withDefaultPlaceholder(ElInputNumber, 'input'),
RadioGroup: (props, { attrs, slots }) => { RadioGroup: (props, { attrs, slots }) => {

View File

@ -37,6 +37,7 @@ import { message } from '#/adapter/naive';
const withDefaultPlaceholder = <T extends Component>( const withDefaultPlaceholder = <T extends Component>(
component: T, component: T,
type: 'input' | 'select', type: 'input' | 'select',
componentProps: Recordable<any> = {},
) => { ) => {
return defineComponent({ return defineComponent({
inheritAttrs: false, inheritAttrs: false,
@ -59,7 +60,11 @@ const withDefaultPlaceholder = <T extends Component>(
} }
}); });
return () => return () =>
h(component, { ...props, ...attrs, placeholder, ref: innerRef }, slots); h(
component,
{ ...componentProps, placeholder, ...props, ...attrs, ref: innerRef },
slots,
);
}, },
}); });
}; };
@ -90,37 +95,19 @@ async function initComponentAdapter() {
// Button: () => // Button: () =>
// import('xxx').then((res) => res.Button), // import('xxx').then((res) => res.Button),
ApiSelect: (props, { attrs, slots }) => { ApiSelect: withDefaultPlaceholder(ApiComponent, 'select', {
return h( component: NSelect,
ApiComponent, modelPropName: 'value',
{ }),
placeholder: $t('ui.placeholder.select'), ApiTreeSelect: withDefaultPlaceholder(ApiComponent, 'select', {
...props, component: NTreeSelect,
...attrs, nodeKey: 'value',
component: NSelect, loadingSlot: 'arrow',
modelPropName: 'value', keyField: 'value',
}, modelPropName: 'value',
slots, optionsPropName: 'options',
); visibleEvent: 'onVisibleChange',
}, }),
ApiTreeSelect: (props, { attrs, slots }) => {
return h(
ApiComponent,
{
placeholder: $t('ui.placeholder.select'),
...props,
...attrs,
component: NTreeSelect,
nodeKey: 'value',
loadingSlot: 'arrow',
keyField: 'value',
modelPropName: 'value',
optionsPropName: 'options',
visibleEvent: 'onVisibleChange',
},
slots,
);
},
Checkbox: NCheckbox, Checkbox: NCheckbox,
CheckboxGroup: (props, { attrs, slots }) => { CheckboxGroup: (props, { attrs, slots }) => {
let defaultSlot; let defaultSlot;
@ -148,13 +135,10 @@ async function initComponentAdapter() {
return h(NButton, { ...props, attrs, type: 'primary' }, slots); return h(NButton, { ...props, attrs, type: 'primary' }, slots);
}, },
Divider: NDivider, Divider: NDivider,
IconPicker: (props, { attrs, slots }) => { IconPicker: withDefaultPlaceholder(IconPicker, 'select', {
return h( iconSlot: 'suffix',
IconPicker, inputComponent: NInput,
{ iconSlot: 'suffix', inputComponent: NInput, ...props, ...attrs }, }),
slots,
);
},
Input: withDefaultPlaceholder(NInput, 'input'), Input: withDefaultPlaceholder(NInput, 'input'),
InputNumber: withDefaultPlaceholder(NInputNumber, 'input'), InputNumber: withDefaultPlaceholder(NInputNumber, 'input'),
RadioGroup: (props, { attrs, slots }) => { RadioGroup: (props, { attrs, slots }) => {

View File

@ -41,6 +41,7 @@ import {
const withDefaultPlaceholder = <T extends Component>( const withDefaultPlaceholder = <T extends Component>(
component: T, component: T,
type: 'input' | 'select', type: 'input' | 'select',
componentProps: Recordable<any> = {},
) => { ) => {
return defineComponent({ return defineComponent({
inheritAttrs: false, inheritAttrs: false,
@ -63,7 +64,11 @@ const withDefaultPlaceholder = <T extends Component>(
} }
}); });
return () => return () =>
h(component, { ...props, ...attrs, placeholder, ref: innerRef }, slots); h(
component,
{ ...componentProps, placeholder, ...props, ...attrs, ref: innerRef },
slots,
);
}, },
}); });
}; };
@ -103,38 +108,20 @@ async function initComponentAdapter() {
// Button: () => // Button: () =>
// import('xxx').then((res) => res.Button), // import('xxx').then((res) => res.Button),
ApiSelect: (props, { attrs, slots }) => { ApiSelect: withDefaultPlaceholder(ApiComponent, 'select', {
return h( component: Select,
ApiComponent, loadingSlot: 'suffixIcon',
{ modelPropName: 'value',
placeholder: $t('ui.placeholder.select'), visibleEvent: 'onVisibleChange',
...props, }),
...attrs, ApiTreeSelect: withDefaultPlaceholder(ApiComponent, 'select', {
component: Select, component: TreeSelect,
loadingSlot: 'suffixIcon', fieldNames: { label: 'label', value: 'value', children: 'children' },
modelPropName: 'value', loadingSlot: 'suffixIcon',
visibleEvent: 'onVisibleChange', modelPropName: 'value',
}, optionsPropName: 'treeData',
slots, visibleEvent: 'onVisibleChange',
); }),
},
ApiTreeSelect: (props, { attrs, slots }) => {
return h(
ApiComponent,
{
placeholder: $t('ui.placeholder.select'),
...props,
...attrs,
component: TreeSelect,
fieldNames: { label: 'label', value: 'value', children: 'children' },
loadingSlot: 'suffixIcon',
modelPropName: 'value',
optionsPropName: 'treeData',
visibleEvent: 'onVisibleChange',
},
slots,
);
},
AutoComplete, AutoComplete,
Checkbox, Checkbox,
CheckboxGroup, CheckboxGroup,
@ -144,19 +131,11 @@ async function initComponentAdapter() {
return h(Button, { ...props, attrs, type: 'default' }, slots); return h(Button, { ...props, attrs, type: 'default' }, slots);
}, },
Divider, Divider,
IconPicker: (props, { attrs, slots }) => { IconPicker: withDefaultPlaceholder(IconPicker, 'select', {
return h( iconSlot: 'addonAfter',
IconPicker, inputComponent: Input,
{ modelValueProp: 'value',
iconSlot: 'addonAfter', }),
inputComponent: Input,
modelValueProp: 'value',
...props,
...attrs,
},
slots,
);
},
Input: withDefaultPlaceholder(Input, 'input'), Input: withDefaultPlaceholder(Input, 'input'),
InputNumber: withDefaultPlaceholder(InputNumber, 'input'), InputNumber: withDefaultPlaceholder(InputNumber, 'input'),
InputPassword: withDefaultPlaceholder(InputPassword, 'input'), InputPassword: withDefaultPlaceholder(InputPassword, 'input'),