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(
ApiComponent,
{
placeholder: $t('ui.placeholder.select'),
...props,
...attrs,
component: Select, component: Select,
loadingSlot: 'suffixIcon', loadingSlot: 'suffixIcon',
visibleEvent: 'onDropdownVisibleChange', visibleEvent: 'onDropdownVisibleChange',
modelPropName: 'value', modelPropName: 'value',
}, }),
slots, ApiTreeSelect: withDefaultPlaceholder(ApiComponent, 'select', {
);
},
ApiTreeSelect: (props, { attrs, slots }) => {
return h(
ApiComponent,
{
placeholder: $t('ui.placeholder.select'),
...props,
...attrs,
component: TreeSelect, component: TreeSelect,
fieldNames: { label: 'label', value: 'value', children: 'children' }, fieldNames: { label: 'label', value: 'value', children: 'children' },
loadingSlot: 'suffixIcon', loadingSlot: 'suffixIcon',
modelPropName: 'value', modelPropName: 'value',
optionsPropName: 'treeData', optionsPropName: 'treeData',
visibleEvent: 'onVisibleChange', 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(
IconPicker,
{
iconSlot: 'addonAfter', iconSlot: 'addonAfter',
inputComponent: Input, inputComponent: Input,
modelValueProp: 'value', 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(
ApiComponent,
{
placeholder: $t('ui.placeholder.select'),
...props,
...attrs,
component: ElSelectV2, component: ElSelectV2,
loadingSlot: 'loading', loadingSlot: 'loading',
visibleEvent: 'onVisibleChange', visibleEvent: 'onVisibleChange',
}, }),
slots, ApiTreeSelect: withDefaultPlaceholder(ApiComponent, 'select', {
);
},
ApiTreeSelect: (props, { attrs, slots }) => {
return h(
ApiComponent,
{
placeholder: $t('ui.placeholder.select'),
...props,
...attrs,
component: ElTreeSelect, component: ElTreeSelect,
props: { label: 'label', children: 'children' }, props: { label: 'label', children: 'children' },
nodeKey: 'value', nodeKey: 'value',
loadingSlot: 'loading', loadingSlot: 'loading',
optionsPropName: 'data', optionsPropName: 'data',
visibleEvent: 'onVisibleChange', 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(
IconPicker,
{
iconSlot: 'append', iconSlot: 'append',
modelValueProp: 'model-value', modelValueProp: 'model-value',
inputComponent: ElInput, 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,26 +95,11 @@ 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(
ApiComponent,
{
placeholder: $t('ui.placeholder.select'),
...props,
...attrs,
component: NSelect, component: NSelect,
modelPropName: 'value', modelPropName: 'value',
}, }),
slots, ApiTreeSelect: withDefaultPlaceholder(ApiComponent, 'select', {
);
},
ApiTreeSelect: (props, { attrs, slots }) => {
return h(
ApiComponent,
{
placeholder: $t('ui.placeholder.select'),
...props,
...attrs,
component: NTreeSelect, component: NTreeSelect,
nodeKey: 'value', nodeKey: 'value',
loadingSlot: 'arrow', loadingSlot: 'arrow',
@ -117,10 +107,7 @@ async function initComponentAdapter() {
modelPropName: 'value', modelPropName: 'value',
optionsPropName: 'options', optionsPropName: 'options',
visibleEvent: 'onVisibleChange', 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(
ApiComponent,
{
placeholder: $t('ui.placeholder.select'),
...props,
...attrs,
component: Select, component: Select,
loadingSlot: 'suffixIcon', loadingSlot: 'suffixIcon',
modelPropName: 'value', modelPropName: 'value',
visibleEvent: 'onVisibleChange', visibleEvent: 'onVisibleChange',
}, }),
slots, ApiTreeSelect: withDefaultPlaceholder(ApiComponent, 'select', {
);
},
ApiTreeSelect: (props, { attrs, slots }) => {
return h(
ApiComponent,
{
placeholder: $t('ui.placeholder.select'),
...props,
...attrs,
component: TreeSelect, component: TreeSelect,
fieldNames: { label: 'label', value: 'value', children: 'children' }, fieldNames: { label: 'label', value: 'value', children: 'children' },
loadingSlot: 'suffixIcon', loadingSlot: 'suffixIcon',
modelPropName: 'value', modelPropName: 'value',
optionsPropName: 'treeData', optionsPropName: 'treeData',
visibleEvent: 'onVisibleChange', 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(
IconPicker,
{
iconSlot: 'addonAfter', iconSlot: 'addonAfter',
inputComponent: Input, inputComponent: Input,
modelValueProp: 'value', 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'),