Skip to content

Commit ae01387

Browse files
committed
refactor: autocomplete
1 parent 365a32b commit ae01387

File tree

3 files changed

+87
-98
lines changed

3 files changed

+87
-98
lines changed

components/auto-complete/index.en-US.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ When there is a need for autocomplete functionality.
2424
| autofocus | get focus when component mounted | boolean | false | |
2525
| backfill | backfill selected item the input when using keyboard | boolean | false | |
2626
| #default (for customize input element) | customize input element | HTMLInputElement / HTMLTextAreaElement | `<Input />` | |
27-
| options | Data source for autocomplete | slot \| [DataSourceItemType](https://github.com/vueComponent/ant-design-vue/blob/724d53b907e577cf5880c1e6742d4c3f924f8f49/components/auto-complete/index.vue#L9)\[] | | |
27+
| options | Data source for autocomplete | [DataSourceItemType](https://github.com/vueComponent/ant-design-vue/blob/724d53b907e577cf5880c1e6742d4c3f924f8f49/components/auto-complete/index.vue#L9)\[] | | |
2828
| option | custom render option by slot | v-slot:option="{value, label, [disabled, key, title]}" | - | 3.0 |
2929
| dropdownMenuStyle | additional style applied to dropdown menu | object | | 1.5.0 |
3030
| defaultActiveFirstOption | Whether active first option by default | boolean | true | |

components/auto-complete/index.tsx

Lines changed: 85 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import type { App, Plugin, VNode, ExtractPropTypes } from 'vue';
2-
import { defineComponent, inject, provide } from 'vue';
2+
import { defineComponent, ref } from 'vue';
33
import Select, { selectProps } from '../select';
44
import PropTypes from '../_util/vue-types';
5-
import { defaultConfigProvider } from '../config-provider';
6-
import { getComponent, getOptionProps, isValidElement, getSlot } from '../_util/props-util';
5+
import { isValidElement, flattenChildren } from '../_util/props-util';
76
import warning from '../_util/warning';
87
import Option from './Option';
98
import OptGroup from './OptGroup';
109
import omit from '../_util/omit';
10+
import useConfigInject from '../_util/hooks/useConfigInject';
1111

1212
function isSelectOptionOrSelectOptGroup(child: any): boolean {
1313
return child?.type?.isSelectOption || child?.type?.isSelectOptGroup;
@@ -46,109 +46,98 @@ const AutoComplete = defineComponent({
4646
slots: ['option'],
4747
Option,
4848
OptGroup,
49-
setup(props, { slots }) {
49+
setup(props, { slots, attrs, expose }) {
5050
warning(
51-
!(props.dataSource !== undefined || 'dataSource' in slots),
51+
!('dataSource' in slots),
5252
'AutoComplete',
53-
'`dataSource` is deprecated, please use `options` instead.',
53+
'`dataSource` slot is deprecated, please use props `options` instead.',
5454
);
55-
return {
56-
configProvider: inject('configProvider', defaultConfigProvider),
57-
popupRef: null,
58-
select: null,
59-
};
60-
},
61-
created() {
62-
provide('savePopupRef', this.savePopupRef);
63-
},
64-
methods: {
65-
savePopupRef(ref: VNode) {
66-
this.popupRef = ref;
67-
},
68-
saveSelect(node: VNode) {
69-
this.select = node;
70-
},
71-
getInputElement() {
72-
const children = getSlot(this);
55+
warning(
56+
!('options' in slots),
57+
'AutoComplete',
58+
'`options` slot is deprecated, please use props `options` instead.',
59+
);
60+
const selectRef = ref();
61+
const getInputElement = () => {
62+
const children = flattenChildren(slots.default?.());
7363
const element = children.length ? children[0] : undefined;
7464
return element;
75-
},
65+
};
7666

77-
focus() {
78-
if (this.select) {
79-
this.select.focus();
80-
}
81-
},
67+
const focus = () => {
68+
selectRef.value?.focus();
69+
};
70+
71+
const blur = () => {
72+
selectRef.value?.blur();
73+
};
8274

83-
blur() {
84-
if (this.select) {
85-
this.select.blur();
75+
expose({
76+
focus,
77+
blur,
78+
});
79+
const { prefixCls } = useConfigInject('select', props);
80+
return () => {
81+
const { size, dataSource, notFoundContent = slots.notFoundContent?.() } = props;
82+
let optionChildren: VNode[];
83+
const { class: className } = attrs;
84+
const cls = {
85+
[className as string]: !!className,
86+
[`${prefixCls.value}-lg`]: size === 'large',
87+
[`${prefixCls.value}-sm`]: size === 'small',
88+
[`${prefixCls.value}-show-search`]: true,
89+
[`${prefixCls.value}-auto-complete`]: true,
90+
};
91+
if (props.options === undefined) {
92+
const childArray = slots.dataSource?.() || slots.options?.() || [];
93+
if (childArray.length && isSelectOptionOrSelectOptGroup(childArray[0])) {
94+
optionChildren = childArray;
95+
} else {
96+
optionChildren = dataSource
97+
? dataSource.map((item: any) => {
98+
if (isValidElement(item)) {
99+
return item;
100+
}
101+
switch (typeof item) {
102+
case 'string':
103+
return (
104+
<Option key={item} value={item}>
105+
{item}
106+
</Option>
107+
);
108+
case 'object':
109+
return (
110+
<Option key={item.value} value={item.value}>
111+
{item.text}
112+
</Option>
113+
);
114+
default:
115+
throw new Error(
116+
'AutoComplete[dataSource] only supports type `string[] | Object[]`.',
117+
);
118+
}
119+
})
120+
: [];
121+
}
86122
}
87-
},
88-
},
89123

90-
render() {
91-
const { size, prefixCls: customizePrefixCls, dataSource } = this;
92-
let optionChildren: VNode[];
93-
const { getPrefixCls } = this.configProvider;
94-
const prefixCls = getPrefixCls('select', customizePrefixCls);
95-
const { class: className } = this.$attrs;
96-
const cls = {
97-
[className as string]: !!className,
98-
[`${prefixCls}-lg`]: size === 'large',
99-
[`${prefixCls}-sm`]: size === 'small',
100-
[`${prefixCls}-show-search`]: true,
101-
[`${prefixCls}-auto-complete`]: true,
102-
};
103-
let childArray = getSlot(this, 'dataSource');
104-
if ('options' in this.$slots) {
105-
childArray = getSlot(this, 'options');
106-
}
107-
if (childArray.length && isSelectOptionOrSelectOptGroup(childArray[0])) {
108-
optionChildren = childArray;
109-
} else {
110-
optionChildren = dataSource
111-
? dataSource.map((item: any) => {
112-
if (isValidElement(item)) {
113-
return item;
114-
}
115-
switch (typeof item) {
116-
case 'string':
117-
return (
118-
<Option key={item} value={item}>
119-
{item}
120-
</Option>
121-
);
122-
case 'object':
123-
return (
124-
<Option key={item.value} value={item.value}>
125-
{item.text}
126-
</Option>
127-
);
128-
default:
129-
throw new Error(
130-
'AutoComplete[dataSource] only supports type `string[] | Object[]`.',
131-
);
132-
}
133-
})
134-
: [];
135-
}
136-
const selectProps = {
137-
...omit(getOptionProps(this) as any, ['dataSource', 'optionLabelProp']),
138-
...this.$attrs,
139-
mode: Select.SECRET_COMBOBOX_MODE_DO_NOT_USE,
140-
// optionLabelProp,
141-
getInputElement: this.getInputElement,
142-
notFoundContent: getComponent(this, 'notFoundContent'),
143-
// placeholder: '',
144-
class: cls,
145-
ref: this.saveSelect,
124+
const selectProps = {
125+
...omit(props, ['dataSource', 'optionLabelProp']),
126+
...attrs,
127+
mode: Select.SECRET_COMBOBOX_MODE_DO_NOT_USE,
128+
// optionLabelProp,
129+
getInputElement,
130+
notFoundContent,
131+
// placeholder: '',
132+
class: cls,
133+
ref: selectRef,
134+
};
135+
return (
136+
<Select {...selectProps} v-slots={{ option: slots.option }}>
137+
{optionChildren}
138+
</Select>
139+
);
146140
};
147-
return (
148-
<Select {...selectProps} v-slots={{ option: this.$slots.option }}>
149-
{optionChildren}
150-
</Select>
151-
);
152141
},
153142
});
154143

components/auto-complete/index.zh-CN.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/qtJm4yt45/AutoComplete.svg
3131
| autofocus | 自动获取焦点 | boolean | false | |
3232
| backfill | 使用键盘选择选项的时候把选中项回填到输入框中 | boolean | false | |
3333
| #default (自定义输入框) | 自定义输入框 | HTMLInputElement / HTMLTextAreaElement | `<Input />` | |
34-
| options | 自动完成的数据源 | slot \| [DataSourceItemType](https://github.com/vueComponent/ant-design-vue/blob/724d53b907e577cf5880c1e6742d4c3f924f8f49/components/auto-complete/index.vue#L9)\[] | | |
34+
| options | 自动完成的数据源 | [DataSourceItemType](https://github.com/vueComponent/ant-design-vue/blob/724d53b907e577cf5880c1e6742d4c3f924f8f49/components/auto-complete/index.vue#L9)\[] | | |
3535
| option | 通过 option 插槽,自定义节点 | v-slot:option="{value, label, [disabled, key, title]}" | - | 3.0 |
3636
| dropdownMenuStyle | dropdown 菜单自定义样式 | object | | 1.5.0 |
3737
| defaultActiveFirstOption | 是否默认高亮第一个选项。 | boolean | true | |

0 commit comments

Comments
 (0)