AutoComplete自动完成 - 图1

AutoComplete 自动完成

输入框自动完成功能。

何时使用

  • 需要一个输入框而不是选择器。
  • 需要输入建议/辅助提示。

和 Select 的区别是:

  • AutoComplete 是一个带提示的文本输入框,用户可以自由输入,关键词是辅助输入
  • Select 是在限定的可选项中进行选择,关键词是选择

代码演示

AutoComplete自动完成 - 图2

基本使用

基本使用。通过 options 设置自动完成的数据源。

  1. <template>
  2. <a-auto-complete
  3. v-model:value="value"
  4. :options="options"
  5. style="width: 200px"
  6. placeholder="input here"
  7. @select="onSelect"
  8. @search="onSearch"
  9. />
  10. </template>
  11. <script lang="ts">
  12. import { defineComponent, ref, watch } from 'vue';
  13. interface MockVal {
  14. value: string;
  15. }
  16. const mockVal = (str: string, repeat = 1): MockVal => {
  17. return {
  18. value: str.repeat(repeat),
  19. };
  20. };
  21. export default defineComponent({
  22. setup() {
  23. const value = ref('');
  24. const options = ref<MockVal[]>([]);
  25. const onSearch = (searchText: string) => {
  26. console.log('searchText');
  27. options.value = !searchText
  28. ? []
  29. : [mockVal(searchText), mockVal(searchText, 2), mockVal(searchText, 3)];
  30. };
  31. const onSelect = (value: string) => {
  32. console.log('onSelect', value);
  33. };
  34. watch(value, () => {
  35. console.log('value', value.value);
  36. });
  37. return {
  38. value,
  39. options,
  40. onSearch,
  41. onSelect,
  42. };
  43. },
  44. });
  45. </script>

AutoComplete自动完成 - 图3

自定义输入组件

自定义输入组件。

  1. <template>
  2. <a-auto-complete
  3. v-model:value="value"
  4. :options="options"
  5. style="width: 200px"
  6. @search="handleSearch"
  7. @select="onSelect"
  8. >
  9. <a-textarea
  10. placeholder="input here"
  11. class="custom"
  12. style="height: 50px"
  13. @keypress="handleKeyPress"
  14. />
  15. </a-auto-complete>
  16. </template>
  17. <script lang="ts">
  18. import { defineComponent, ref } from 'vue';
  19. export default defineComponent({
  20. setup() {
  21. const value = ref('');
  22. const options = ref<{ value: string }[]>([]);
  23. const onSelect = (value: string) => {
  24. console.log('onSelect', value);
  25. };
  26. const handleSearch = (value: string) => {
  27. options.value = !value
  28. ? []
  29. : [{ value }, { value: value + value }, { value: value + value + value }];
  30. };
  31. const handleKeyPress = (ev: KeyboardEvent) => {
  32. console.log('handleKeyPress', ev);
  33. };
  34. return {
  35. value,
  36. options,
  37. onSelect,
  38. handleSearch,
  39. handleKeyPress,
  40. };
  41. },
  42. });
  43. </script>

AutoComplete自动完成 - 图4

查询模式 - 确定类目

查询模式 - 确定类目。

  1. <template>
  2. <div class="certain-category-search-wrapper" style="width: 250px">
  3. <a-auto-complete
  4. v-model:value="value"
  5. class="certain-category-search"
  6. dropdown-class-name="certain-category-search-dropdown"
  7. :dropdown-match-select-width="false"
  8. :dropdown-style="{ width: '300px' }"
  9. size="large"
  10. style="width: 100%"
  11. placeholder="input here"
  12. option-label-prop="value"
  13. >
  14. <template #dataSource>
  15. <a-select-opt-group v-for="group in dataSource" :key="group.title">
  16. <template #label>
  17. <span>
  18. {{ group.title }}
  19. <a
  20. style="float: right"
  21. href="https://www.google.com/search?q=antd"
  22. target="_blank"
  23. rel="noopener noreferrer"
  24. >
  25. more
  26. </a>
  27. </span>
  28. </template>
  29. <a-select-option v-for="opt in group.children" :key="opt.title" :value="opt.title">
  30. {{ opt.title }}
  31. <span class="certain-search-item-count">{{ opt.count }} people</span>
  32. </a-select-option>
  33. </a-select-opt-group>
  34. <a-select-option key="all" disabled class="show-all">
  35. <a
  36. href="https://www.google.com/search?q=ant-design-vue"
  37. target="_blank"
  38. rel="noopener noreferrer"
  39. >
  40. View all results
  41. </a>
  42. </a-select-option>
  43. </template>
  44. <a-input>
  45. <template #suffix><search-outlined class="certain-category-icon" /></template>
  46. </a-input>
  47. </a-auto-complete>
  48. </div>
  49. </template>
  50. <script lang="ts">
  51. import { SearchOutlined } from '@ant-design/icons-vue';
  52. import { defineComponent, ref } from 'vue';
  53. const dataSource = [
  54. {
  55. title: 'Libraries',
  56. children: [
  57. {
  58. title: 'AntDesign',
  59. count: 10000,
  60. },
  61. {
  62. title: 'AntDesign UI',
  63. count: 10600,
  64. },
  65. ],
  66. },
  67. {
  68. title: 'Solutions',
  69. children: [
  70. {
  71. title: 'AntDesign UI FAQ',
  72. count: 60100,
  73. },
  74. {
  75. title: 'AntDesign FAQ',
  76. count: 30010,
  77. },
  78. ],
  79. },
  80. {
  81. title: 'Articles',
  82. children: [
  83. {
  84. title: 'AntDesign design language',
  85. count: 100000,
  86. },
  87. ],
  88. },
  89. ];
  90. export default defineComponent({
  91. setup() {
  92. return {
  93. value: ref(''),
  94. dataSource,
  95. };
  96. },
  97. components: {
  98. SearchOutlined,
  99. },
  100. });
  101. </script>
  102. <style>
  103. .certain-category-search-dropdown .ant-select-dropdown-menu-item-group-title {
  104. color: #666;
  105. font-weight: bold;
  106. }
  107. .certain-category-search-dropdown .ant-select-dropdown-menu-item-group {
  108. border-bottom: 1px solid #f6f6f6;
  109. }
  110. .certain-category-search-dropdown .ant-select-dropdown-menu-item {
  111. padding-left: 16px;
  112. }
  113. .certain-category-search-dropdown .ant-select-dropdown-menu-item.show-all {
  114. text-align: center;
  115. cursor: default;
  116. }
  117. .certain-category-search-dropdown .ant-select-dropdown-menu {
  118. max-height: 300px;
  119. }
  120. </style>
  121. <style scoped>
  122. .certain-category-search-wrapper
  123. :deep(.certain-category-search.ant-select-auto-complete)
  124. .ant-input-affix-wrapper
  125. .ant-input-suffix {
  126. right: 12px;
  127. }
  128. .certain-category-search-wrapper :deep(.certain-search-item-count) {
  129. position: absolute;
  130. color: #999;
  131. right: 16px;
  132. }
  133. .certain-category-search-wrapper
  134. :deep(.certain-category-search.ant-select-focused)
  135. .certain-category-icon {
  136. color: #108ee9;
  137. }
  138. .certain-category-search-wrapper :deep(.certain-category-icon) {
  139. color: #6e6e6e;
  140. transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
  141. font-size: 16px;
  142. }
  143. </style>

AutoComplete自动完成 - 图5

自定义选项

也可以直接传递 #dataSource 的Option。

  1. <template>
  2. <a-auto-complete
  3. v-model:value="value"
  4. style="width: 200px"
  5. placeholder="input here"
  6. @search="handleSearch"
  7. >
  8. <template #dataSource>
  9. <a-select-option v-for="email in result" :key="email">
  10. {{ email }}
  11. </a-select-option>
  12. </template>
  13. </a-auto-complete>
  14. </template>
  15. <script lang="ts">
  16. import { defineComponent, ref } from 'vue';
  17. export default defineComponent({
  18. setup() {
  19. const value = ref('');
  20. const result = ref<string[]>([]);
  21. const handleSearch = (val: string) => {
  22. let res: string[];
  23. if (!val || val.indexOf('@') >= 0) {
  24. res = [];
  25. } else {
  26. res = ['gmail.com', '163.com', 'qq.com'].map(domain => `${val}@${domain}`);
  27. }
  28. result.value = res;
  29. };
  30. return {
  31. value,
  32. result,
  33. handleSearch,
  34. };
  35. },
  36. });
  37. </script>

AutoComplete自动完成 - 图6

不区分大小写

不区分大小写的 AutoComplete。

  1. <template>
  2. <a-auto-complete
  3. v-model:value="value"
  4. :options="options"
  5. style="width: 200px"
  6. placeholder="input here"
  7. :filter-option="filterOption"
  8. />
  9. </template>
  10. <script lang="ts">
  11. import { defineComponent, ref } from 'vue';
  12. interface Option {
  13. value: string;
  14. }
  15. export default defineComponent({
  16. setup() {
  17. const filterOption = (input: string, option: Option) => {
  18. return option.value.toUpperCase().indexOf(input.toUpperCase()) >= 0;
  19. };
  20. return {
  21. value: ref(''),
  22. options: ref<Option[]>([
  23. { value: 'Burns Bay Road' },
  24. { value: 'Downing Street' },
  25. { value: 'Wall Street' },
  26. ]),
  27. filterOption,
  28. };
  29. },
  30. });
  31. </script>

AutoComplete自动完成 - 图7

查询模式 - 不确定类目

查询模式 - 不确定类目。

  1. <template>
  2. <div class="global-search-wrapper" style="width: 300px">
  3. <a-auto-complete
  4. v-model:value="value"
  5. class="global-search"
  6. size="large"
  7. style="width: 100%"
  8. option-label-prop="title"
  9. @select="onSelect"
  10. @search="handleSearch"
  11. >
  12. <template #dataSource>
  13. <a-select-option v-for="item in dataSource" :key="item.category" :title="item.category">
  14. Found {{ item.query }} on
  15. <a
  16. :href="`https://s.taobao.com/search?q=${item.query}`"
  17. target="_blank"
  18. rel="noopener noreferrer"
  19. >
  20. {{ item.category }}
  21. </a>
  22. <span class="global-search-item-count">{{ item.count }} results</span>
  23. </a-select-option>
  24. </template>
  25. <a-input-search size="large" placeholder="input here" enterButton></a-input-search>
  26. </a-auto-complete>
  27. </div>
  28. </template>
  29. <script lang="ts">
  30. import { defineComponent, ref } from 'vue';
  31. interface Option {
  32. query: string;
  33. category: string;
  34. count: number;
  35. }
  36. export default defineComponent({
  37. setup() {
  38. const value = ref('');
  39. const dataSource = ref<Option[]>([]);
  40. const onSelect = (value: string) => {
  41. console.log('onSelect', value);
  42. };
  43. const getRandomInt = (max: number, min = 0) => {
  44. return Math.floor(Math.random() * (max - min + 1)) + min;
  45. };
  46. const searchResult = (query: string): Option[] => {
  47. return new Array(getRandomInt(5))
  48. .join('.')
  49. .split('.')
  50. .map((item, idx) => ({
  51. query,
  52. category: `${query}${idx}`,
  53. count: getRandomInt(200, 100),
  54. }));
  55. };
  56. const handleSearch = (val: string) => {
  57. dataSource.value = val ? searchResult(val) : [];
  58. };
  59. return {
  60. value,
  61. dataSource,
  62. onSelect,
  63. handleSearch,
  64. };
  65. },
  66. });
  67. </script>
  68. <style>
  69. .global-search-wrapper {
  70. padding-right: 50px;
  71. }
  72. .global-search {
  73. width: 100%;
  74. }
  75. .global-search.ant-select-auto-complete .ant-select-selection--single {
  76. margin-right: -46px;
  77. }
  78. .global-search.ant-select-auto-complete .ant-input-affix-wrapper .ant-input:not(:last-child) {
  79. padding-right: 62px;
  80. }
  81. .global-search.ant-select-auto-complete .ant-input-affix-wrapper .ant-input-suffix button {
  82. border-top-left-radius: 0;
  83. border-bottom-left-radius: 0;
  84. }
  85. .global-search-item {
  86. display: flex;
  87. }
  88. .global-search-item-desc {
  89. flex: auto;
  90. text-overflow: ellipsis;
  91. overflow: hidden;
  92. }
  93. .global-search-item-count {
  94. flex: none;
  95. }
  96. </style>

API

  1. <a-auto-complete v-model:value="value" :options="options" />
参数说明类型默认值版本
allowClear支持清除, 单选模式有效booleanfalse
autofocus自动获取焦点booleanfalse
backfill使用键盘选择选项的时候把选中项回填到输入框中booleanfalse
#default (自定义输入框)自定义输入框HTMLInputElement / HTMLTextAreaElement<Input />
options自动完成的数据源slot | DataSourceItemType[]
dropdownMenuStyledropdown 菜单自定义样式object1.5.0
defaultActiveFirstOption是否默认高亮第一个选项。booleantrue
disabled是否禁用booleanfalse
filterOption是否根据输入项进行筛选。当其为一个函数时,会接收 inputValue option 两个参数,当 option 符合筛选条件时,应返回 true,反之则返回 falseboolean or function(inputValue, option)true
optionLabelProp回填到选择框的 Option 的属性值,默认是 Option 的子元素。比如在子元素需要高亮效果时,此值可以设为 valuestringchildren
placeholder输入框提示string | slot-
v-model:value指定当前选中的条目string|string[]|{ key: string, label: string|vNodes }|Array<{ key: string, label: string|vNodes }>
defaultOpen是否默认展开下拉菜单boolean-
open是否展开下拉菜单boolean-

事件

事件名称说明回调参数版本
change选中 option,或 input 的 value 变化时,调用此函数function(value)
blur失去焦点时的回调function()
focus获得焦点时的回调function()
search搜索补全项的时候调用function(value)
select被选中时调用,参数为选中项的 value 值function(value, option)
dropdownVisibleChange展开下拉菜单的回调function(open)

方法

名称描述版本
blur()移除焦点
focus()获取焦点