Browse Source

refactor: autocomplete

v2.3
tangjinzhou 3 years ago
parent
commit
ae01387d90
  1. 2
      components/auto-complete/index.en-US.md
  2. 181
      components/auto-complete/index.tsx
  3. 2
      components/auto-complete/index.zh-CN.md

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

@ -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 | |

181
components/auto-complete/index.tsx

@ -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,109 +46,98 @@ 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(); };
}
}, const blur = () => {
selectRef.value?.blur();
};
blur() { expose({
if (this.select) { focus,
this.select.blur(); blur,
});
const { prefixCls } = useConfigInject('select', props);
return () => {
const { size, dataSource, notFoundContent = slots.notFoundContent?.() } = props;
let optionChildren: VNode[];
const { class: className } = attrs;
const cls = {
[className as string]: !!className,
[`${prefixCls.value}-lg`]: size === 'large',
[`${prefixCls.value}-sm`]: size === 'small',
[`${prefixCls.value}-show-search`]: true,
[`${prefixCls.value}-auto-complete`]: true,
};
if (props.options === undefined) {
const childArray = slots.dataSource?.() || slots.options?.() || [];
if (childArray.length && isSelectOptionOrSelectOptGroup(childArray[0])) {
optionChildren = childArray;
} else {
optionChildren = dataSource
? dataSource.map((item: any) => {
if (isValidElement(item)) {
return item;
}
switch (typeof item) {
case 'string':
return (
<Option key={item} value={item}>
{item}
</Option>
);
case 'object':
return (
<Option key={item.value} value={item.value}>
{item.text}
</Option>
);
default:
throw new Error(
'AutoComplete[dataSource] only supports type `string[] | Object[]`.',
);
}
})
: [];
}
} }
},
},
render() { const selectProps = {
const { size, prefixCls: customizePrefixCls, dataSource } = this; ...omit(props, ['dataSource', 'optionLabelProp']),
let optionChildren: VNode[]; ...attrs,
const { getPrefixCls } = this.configProvider; mode: Select.SECRET_COMBOBOX_MODE_DO_NOT_USE,
const prefixCls = getPrefixCls('select', customizePrefixCls); // optionLabelProp,
const { class: className } = this.$attrs; getInputElement,
const cls = { notFoundContent,
[className as string]: !!className, // placeholder: '',
[`${prefixCls}-lg`]: size === 'large', class: cls,
[`${prefixCls}-sm`]: size === 'small', ref: selectRef,
[`${prefixCls}-show-search`]: true, };
[`${prefixCls}-auto-complete`]: true, return (
}; <Select {...selectProps} v-slots={{ option: slots.option }}>
let childArray = getSlot(this, 'dataSource'); {optionChildren}
if ('options' in this.$slots) { </Select>
childArray = getSlot(this, 'options'); );
}
if (childArray.length && isSelectOptionOrSelectOptGroup(childArray[0])) {
optionChildren = childArray;
} else {
optionChildren = dataSource
? dataSource.map((item: any) => {
if (isValidElement(item)) {
return item;
}
switch (typeof item) {
case 'string':
return (
<Option key={item} value={item}>
{item}
</Option>
);
case 'object':
return (
<Option key={item.value} value={item.value}>
{item.text}
</Option>
);
default:
throw new Error(
'AutoComplete[dataSource] only supports type `string[] | Object[]`.',
);
}
})
: [];
}
const selectProps = {
...omit(getOptionProps(this) as any, ['dataSource', 'optionLabelProp']),
...this.$attrs,
mode: Select.SECRET_COMBOBOX_MODE_DO_NOT_USE,
// optionLabelProp,
getInputElement: this.getInputElement,
notFoundContent: getComponent(this, 'notFoundContent'),
// placeholder: '',
class: cls,
ref: this.saveSelect,
}; };
return (
<Select {...selectProps} v-slots={{ option: this.$slots.option }}>
{optionChildren}
</Select>
);
}, },
}); });

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

@ -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…
Cancel
Save