refactor: autocomplete
parent
365a32be26
commit
ae01387d90
|
@ -24,7 +24,7 @@ When there is a need for autocomplete functionality.
|
||||||
| autofocus | get focus when component mounted | boolean | false | |
|
| autofocus | get focus when component mounted | boolean | false | |
|
||||||
| backfill | backfill selected item the input when using keyboard | boolean | false | |
|
| backfill | backfill selected item the input when using keyboard | boolean | false | |
|
||||||
| #default (for customize input element) | customize input element | HTMLInputElement / HTMLTextAreaElement | `<Input />` | |
|
| #default (for customize input element) | customize input element | HTMLInputElement / HTMLTextAreaElement | `<Input />` | |
|
||||||
| options | Data source for autocomplete | slot \| [DataSourceItemType](https://github.com/vueComponent/ant-design-vue/blob/724d53b907e577cf5880c1e6742d4c3f924f8f49/components/auto-complete/index.vue#L9)\[] | | |
|
| options | Data source for autocomplete | [DataSourceItemType](https://github.com/vueComponent/ant-design-vue/blob/724d53b907e577cf5880c1e6742d4c3f924f8f49/components/auto-complete/index.vue#L9)\[] | | |
|
||||||
| option | custom render option by slot | v-slot:option="{value, label, [disabled, key, title]}" | - | 3.0 |
|
| option | custom render option by slot | v-slot:option="{value, label, [disabled, key, title]}" | - | 3.0 |
|
||||||
| dropdownMenuStyle | additional style applied to dropdown menu | object | | 1.5.0 |
|
| dropdownMenuStyle | additional style applied to dropdown menu | object | | 1.5.0 |
|
||||||
| defaultActiveFirstOption | Whether active first option by default | boolean | true | |
|
| defaultActiveFirstOption | Whether active first option by default | boolean | true | |
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import type { App, Plugin, VNode, ExtractPropTypes } from 'vue';
|
import type { App, Plugin, VNode, ExtractPropTypes } from 'vue';
|
||||||
import { defineComponent, inject, provide } from 'vue';
|
import { defineComponent, ref } from 'vue';
|
||||||
import Select, { selectProps } from '../select';
|
import Select, { selectProps } from '../select';
|
||||||
import PropTypes from '../_util/vue-types';
|
import PropTypes from '../_util/vue-types';
|
||||||
import { defaultConfigProvider } from '../config-provider';
|
import { isValidElement, flattenChildren } from '../_util/props-util';
|
||||||
import { getComponent, getOptionProps, isValidElement, getSlot } from '../_util/props-util';
|
|
||||||
import warning from '../_util/warning';
|
import warning from '../_util/warning';
|
||||||
import Option from './Option';
|
import Option from './Option';
|
||||||
import OptGroup from './OptGroup';
|
import OptGroup from './OptGroup';
|
||||||
import omit from '../_util/omit';
|
import omit from '../_util/omit';
|
||||||
|
import useConfigInject from '../_util/hooks/useConfigInject';
|
||||||
|
|
||||||
function isSelectOptionOrSelectOptGroup(child: any): boolean {
|
function isSelectOptionOrSelectOptGroup(child: any): boolean {
|
||||||
return child?.type?.isSelectOption || child?.type?.isSelectOptGroup;
|
return child?.type?.isSelectOption || child?.type?.isSelectOptGroup;
|
||||||
|
@ -46,64 +46,50 @@ const AutoComplete = defineComponent({
|
||||||
slots: ['option'],
|
slots: ['option'],
|
||||||
Option,
|
Option,
|
||||||
OptGroup,
|
OptGroup,
|
||||||
setup(props, { slots }) {
|
setup(props, { slots, attrs, expose }) {
|
||||||
warning(
|
warning(
|
||||||
!(props.dataSource !== undefined || 'dataSource' in slots),
|
!('dataSource' in slots),
|
||||||
'AutoComplete',
|
'AutoComplete',
|
||||||
'`dataSource` is deprecated, please use `options` instead.',
|
'`dataSource` slot is deprecated, please use props `options` instead.',
|
||||||
);
|
);
|
||||||
return {
|
warning(
|
||||||
configProvider: inject('configProvider', defaultConfigProvider),
|
!('options' in slots),
|
||||||
popupRef: null,
|
'AutoComplete',
|
||||||
select: null,
|
'`options` slot is deprecated, please use props `options` instead.',
|
||||||
};
|
);
|
||||||
},
|
const selectRef = ref();
|
||||||
created() {
|
const getInputElement = () => {
|
||||||
provide('savePopupRef', this.savePopupRef);
|
const children = flattenChildren(slots.default?.());
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
savePopupRef(ref: VNode) {
|
|
||||||
this.popupRef = ref;
|
|
||||||
},
|
|
||||||
saveSelect(node: VNode) {
|
|
||||||
this.select = node;
|
|
||||||
},
|
|
||||||
getInputElement() {
|
|
||||||
const children = getSlot(this);
|
|
||||||
const element = children.length ? children[0] : undefined;
|
const element = children.length ? children[0] : undefined;
|
||||||
return element;
|
return element;
|
||||||
},
|
};
|
||||||
|
|
||||||
focus() {
|
const focus = () => {
|
||||||
if (this.select) {
|
selectRef.value?.focus();
|
||||||
this.select.focus();
|
};
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
blur() {
|
const blur = () => {
|
||||||
if (this.select) {
|
selectRef.value?.blur();
|
||||||
this.select.blur();
|
};
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
render() {
|
expose({
|
||||||
const { size, prefixCls: customizePrefixCls, dataSource } = this;
|
focus,
|
||||||
|
blur,
|
||||||
|
});
|
||||||
|
const { prefixCls } = useConfigInject('select', props);
|
||||||
|
return () => {
|
||||||
|
const { size, dataSource, notFoundContent = slots.notFoundContent?.() } = props;
|
||||||
let optionChildren: VNode[];
|
let optionChildren: VNode[];
|
||||||
const { getPrefixCls } = this.configProvider;
|
const { class: className } = attrs;
|
||||||
const prefixCls = getPrefixCls('select', customizePrefixCls);
|
|
||||||
const { class: className } = this.$attrs;
|
|
||||||
const cls = {
|
const cls = {
|
||||||
[className as string]: !!className,
|
[className as string]: !!className,
|
||||||
[`${prefixCls}-lg`]: size === 'large',
|
[`${prefixCls.value}-lg`]: size === 'large',
|
||||||
[`${prefixCls}-sm`]: size === 'small',
|
[`${prefixCls.value}-sm`]: size === 'small',
|
||||||
[`${prefixCls}-show-search`]: true,
|
[`${prefixCls.value}-show-search`]: true,
|
||||||
[`${prefixCls}-auto-complete`]: true,
|
[`${prefixCls.value}-auto-complete`]: true,
|
||||||
};
|
};
|
||||||
let childArray = getSlot(this, 'dataSource');
|
if (props.options === undefined) {
|
||||||
if ('options' in this.$slots) {
|
const childArray = slots.dataSource?.() || slots.options?.() || [];
|
||||||
childArray = getSlot(this, 'options');
|
|
||||||
}
|
|
||||||
if (childArray.length && isSelectOptionOrSelectOptGroup(childArray[0])) {
|
if (childArray.length && isSelectOptionOrSelectOptGroup(childArray[0])) {
|
||||||
optionChildren = childArray;
|
optionChildren = childArray;
|
||||||
} else {
|
} else {
|
||||||
|
@ -133,22 +119,25 @@ const AutoComplete = defineComponent({
|
||||||
})
|
})
|
||||||
: [];
|
: [];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const selectProps = {
|
const selectProps = {
|
||||||
...omit(getOptionProps(this) as any, ['dataSource', 'optionLabelProp']),
|
...omit(props, ['dataSource', 'optionLabelProp']),
|
||||||
...this.$attrs,
|
...attrs,
|
||||||
mode: Select.SECRET_COMBOBOX_MODE_DO_NOT_USE,
|
mode: Select.SECRET_COMBOBOX_MODE_DO_NOT_USE,
|
||||||
// optionLabelProp,
|
// optionLabelProp,
|
||||||
getInputElement: this.getInputElement,
|
getInputElement,
|
||||||
notFoundContent: getComponent(this, 'notFoundContent'),
|
notFoundContent,
|
||||||
// placeholder: '',
|
// placeholder: '',
|
||||||
class: cls,
|
class: cls,
|
||||||
ref: this.saveSelect,
|
ref: selectRef,
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<Select {...selectProps} v-slots={{ option: this.$slots.option }}>
|
<Select {...selectProps} v-slots={{ option: slots.option }}>
|
||||||
{optionChildren}
|
{optionChildren}
|
||||||
</Select>
|
</Select>
|
||||||
);
|
);
|
||||||
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/qtJm4yt45/AutoComplete.svg
|
||||||
| autofocus | 自动获取焦点 | boolean | false | |
|
| autofocus | 自动获取焦点 | boolean | false | |
|
||||||
| backfill | 使用键盘选择选项的时候把选中项回填到输入框中 | boolean | false | |
|
| backfill | 使用键盘选择选项的时候把选中项回填到输入框中 | boolean | false | |
|
||||||
| #default (自定义输入框) | 自定义输入框 | HTMLInputElement / HTMLTextAreaElement | `<Input />` | |
|
| #default (自定义输入框) | 自定义输入框 | HTMLInputElement / HTMLTextAreaElement | `<Input />` | |
|
||||||
| options | 自动完成的数据源 | slot \| [DataSourceItemType](https://github.com/vueComponent/ant-design-vue/blob/724d53b907e577cf5880c1e6742d4c3f924f8f49/components/auto-complete/index.vue#L9)\[] | | |
|
| options | 自动完成的数据源 | [DataSourceItemType](https://github.com/vueComponent/ant-design-vue/blob/724d53b907e577cf5880c1e6742d4c3f924f8f49/components/auto-complete/index.vue#L9)\[] | | |
|
||||||
| option | 通过 option 插槽,自定义节点 | v-slot:option="{value, label, [disabled, key, title]}" | - | 3.0 |
|
| option | 通过 option 插槽,自定义节点 | v-slot:option="{value, label, [disabled, key, title]}" | - | 3.0 |
|
||||||
| dropdownMenuStyle | dropdown 菜单自定义样式 | object | | 1.5.0 |
|
| dropdownMenuStyle | dropdown 菜单自定义样式 | object | | 1.5.0 |
|
||||||
| defaultActiveFirstOption | 是否默认高亮第一个选项。 | boolean | true | |
|
| defaultActiveFirstOption | 是否默认高亮第一个选项。 | boolean | true | |
|
||||||
|
|
Loading…
Reference in New Issue