Skip to content

Commit 38258d3

Browse files
committed
refactor: dropdown
1 parent f71a722 commit 38258d3

22 files changed

+682
-733
lines changed

components/dropdown/__tests__/__snapshots__/dropdown-button.test.js.snap

+1-3
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ exports[`DropdownButton should support href like Button 1`] = `
44
<div class="ant-btn-group ant-dropdown-button"><a class="ant-btn ant-btn-default" href="https://ant.design">
55
<!---->
66
</a>
7-
<!----><button class="ant-btn ant-btn-default ant-dropdown-trigger" type="button">
8-
<!----><span role="img" aria-label="ellipsis" class="anticon anticon-ellipsis"><svg focusable="false" class="" data-icon="ellipsis" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M176 511a56 56 0 10112 0 56 56 0 10-112 0zm280 0a56 56 0 10112 0 56 56 0 10-112 0zm280 0a56 56 0 10112 0 56 56 0 10-112 0z"></path></svg></span>
9-
</button>
7+
<!----><button class="ant-btn ant-btn-default ant-dropdown-trigger ant-btn-icon-only" type="button"><span role="img" aria-label="ellipsis" class="anticon anticon-ellipsis"><svg focusable="false" class="" data-icon="ellipsis" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M176 511a56 56 0 10112 0 56 56 0 10-112 0zm280 0a56 56 0 10112 0 56 56 0 10-112 0zm280 0a56 56 0 10112 0 56 56 0 10-112 0z"></path></svg></span></button>
108
</div>
119
`;

components/dropdown/__tests__/dropdown-button.test.js

+9-7
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ describe('DropdownButton', () => {
2424

2525
it("don't pass visible to Dropdown if it's not exits", () => {
2626
const wrapper = mount(Dropdown.Button, {
27-
props: {
28-
overlay: (
27+
slots: {
28+
overlay: () => (
2929
<Menu>
3030
<Menu.Item>foo</Menu.Item>
3131
</Menu>
@@ -43,11 +43,13 @@ describe('DropdownButton', () => {
4343
return (
4444
<Dropdown.Button
4545
href="https://ant.design"
46-
overlay={
47-
<Menu>
48-
<Menu.Item>foo</Menu.Item>
49-
</Menu>
50-
}
46+
v-slots={{
47+
overlay: () => (
48+
<Menu>
49+
<Menu.Item>foo</Menu.Item>
50+
</Menu>
51+
),
52+
}}
5153
/>
5254
);
5355
},
+71-96
Original file line numberDiff line numberDiff line change
@@ -1,117 +1,92 @@
1-
import type { VNode, ExtractPropTypes } from 'vue';
2-
import { provide, inject, defineComponent } from 'vue';
1+
import { ExtractPropTypes } from 'vue';
2+
import { defineComponent } from 'vue';
33
import Button from '../button';
44
import classNames from '../_util/classNames';
5-
import buttonTypes from '../button/buttonTypes';
65
import Dropdown from './dropdown';
7-
import PropTypes from '../_util/vue-types';
8-
import { hasProp, getComponent, getSlot } from '../_util/props-util';
9-
import getDropdownProps from './getDropdownProps';
10-
import { defaultConfigProvider } from '../config-provider';
6+
import { initDefaultProps } from '../_util/props-util';
7+
import { dropdownButtonProps } from './props';
118
import EllipsisOutlined from '@ant-design/icons-vue/EllipsisOutlined';
12-
import { tuple } from '../_util/type';
13-
14-
const ButtonTypesProps = buttonTypes();
15-
const DropdownProps = getDropdownProps();
9+
import useConfigInject from '../_util/hooks/useConfigInject';
1610
const ButtonGroup = Button.Group;
17-
const dropdownButtonProps = {
18-
...DropdownProps,
19-
type: PropTypes.oneOf(tuple('primary', 'ghost', 'dashed', 'danger', 'default')).def('default'),
20-
size: PropTypes.oneOf(tuple('small', 'large', 'default')).def('default'),
21-
htmlType: ButtonTypesProps.htmlType,
22-
href: PropTypes.string,
23-
disabled: PropTypes.looseBool,
24-
prefixCls: PropTypes.string,
25-
placement: DropdownProps.placement.def('bottomRight'),
26-
icon: PropTypes.any,
27-
title: PropTypes.string,
28-
onClick: PropTypes.func,
29-
onVisibleChange: PropTypes.func,
30-
'onUpdate:visible': PropTypes.func,
31-
};
32-
export type DropdownButtonProps = Partial<ExtractPropTypes<typeof dropdownButtonProps>>;
11+
12+
export type DropdownButtonProps = Partial<ExtractPropTypes<ReturnType<typeof dropdownButtonProps>>>;
13+
3314
export default defineComponent({
3415
name: 'ADropdownButton',
3516
inheritAttrs: false,
36-
props: dropdownButtonProps,
17+
__ANT_BUTTON: true,
18+
props: initDefaultProps(dropdownButtonProps(), {
19+
trigger: 'hover',
20+
placement: 'bottomRight',
21+
type: 'default',
22+
}),
3723
emits: ['click', 'visibleChange', 'update:visible'],
38-
setup() {
39-
return {
40-
configProvider: inject('configProvider', defaultConfigProvider),
41-
popupRef: null,
24+
slots: ['icon', 'leftButton', 'rightButton', 'overlay'],
25+
setup(props, { slots, attrs, emit }) {
26+
const handleClick = (e: MouseEvent) => {
27+
emit('click', e);
4228
};
43-
},
44-
created() {
45-
provide('savePopupRef', this.savePopupRef);
46-
},
47-
methods: {
48-
savePopupRef(ref: VNode) {
49-
this.popupRef = ref;
50-
},
51-
handleClick(e: Event) {
52-
this.$emit('click', e);
53-
},
54-
handleVisibleChange(val: boolean) {
55-
this.$emit('update:visible', val);
56-
this.$emit('visibleChange', val);
57-
},
58-
},
59-
render() {
60-
const {
61-
type,
62-
disabled,
63-
onClick,
64-
htmlType,
65-
class: className,
66-
prefixCls: customizePrefixCls,
67-
overlay,
68-
trigger,
69-
align,
70-
visible,
71-
onVisibleChange,
72-
placement,
73-
getPopupContainer,
74-
href,
75-
title,
76-
...restProps
77-
} = { ...this.$props, ...this.$attrs } as any;
78-
const icon = getComponent(this, 'icon') || <EllipsisOutlined />;
79-
const { getPopupContainer: getContextPopupContainer } = this.configProvider;
80-
const getPrefixCls = this.configProvider.getPrefixCls;
81-
const prefixCls = getPrefixCls('dropdown-button', customizePrefixCls);
82-
const dropdownProps: any = {
83-
align,
84-
disabled,
85-
trigger: disabled ? [] : trigger,
86-
placement,
87-
getPopupContainer: getPopupContainer || getContextPopupContainer,
88-
onVisibleChange: this.handleVisibleChange,
29+
const handleVisibleChange = (val: boolean) => {
30+
emit('update:visible', val);
31+
emit('visibleChange', val);
8932
};
90-
if (hasProp(this, 'visible')) {
91-
dropdownProps.visible = visible;
92-
}
9333

94-
const buttonGroupProps = {
95-
...restProps,
96-
class: classNames(prefixCls, className),
97-
};
34+
const { prefixCls, direction, getPopupContainer } = useConfigInject('dropdown-button', props);
35+
36+
return () => {
37+
const {
38+
type,
39+
disabled,
40+
htmlType,
41+
class: className = '',
42+
overlay = slots.overlay?.(),
43+
trigger,
44+
align,
45+
visible,
46+
onVisibleChange,
47+
placement = direction.value === 'rtl' ? 'bottomLeft' : 'bottomRight',
48+
href,
49+
title,
50+
icon = slots.icon?.() || <EllipsisOutlined />,
51+
mouseEnterDelay,
52+
mouseLeaveDelay,
53+
...restProps
54+
} = { ...props, ...attrs };
55+
56+
const dropdownProps = {
57+
align,
58+
disabled,
59+
trigger: disabled ? [] : trigger,
60+
placement,
61+
getPopupContainer: getPopupContainer.value,
62+
onVisibleChange: handleVisibleChange,
63+
mouseEnterDelay,
64+
mouseLeaveDelay,
65+
visible,
66+
};
9867

99-
return (
100-
<ButtonGroup {...buttonGroupProps}>
68+
const leftButton = (
10169
<Button
10270
type={type}
10371
disabled={disabled}
104-
onClick={this.handleClick}
72+
onClick={handleClick}
10573
htmlType={htmlType}
10674
href={href}
10775
title={title}
108-
>
109-
{getSlot(this)}
110-
</Button>
111-
<Dropdown {...dropdownProps} overlay={getComponent(this, 'overlay')}>
112-
<Button type={type}>{icon}</Button>
113-
</Dropdown>
114-
</ButtonGroup>
115-
);
76+
v-slots={{ default: slots.default }}
77+
></Button>
78+
);
79+
80+
const rightButton = <Button type={type} icon={icon} />;
81+
82+
return (
83+
<ButtonGroup {...restProps} class={classNames(prefixCls.value, className)}>
84+
{slots.leftButton ? slots.leftButton({ button: leftButton }) : leftButton}
85+
<Dropdown {...dropdownProps} v-slots={{ overlay: slots.overlay }}>
86+
{slots.rightButton ? slots.rightButton({ button: rightButton }) : rightButton}
87+
</Dropdown>
88+
</ButtonGroup>
89+
);
90+
};
11691
},
11792
});

0 commit comments

Comments
 (0)