跳转到内容

Autocomplete 自动补全组件

自动补全是一个普通文本输入框,它通过一组建议的选项来帮助用户输入。

该组件常用于以下两个场景中的单行文本框赋值:

  1. 文本框必须取值于某个预设好的,例如:一个位置域必须包含一个有效的位置名称: 组合框
  2. 文本框也可以是任何值,但最好能够为用户提供可能的选项,譬如搜索框可以提供近似的或者曾搜索过的选项以节省用户时间:灵活的单文本框

此组件旨在改进 “react-select” 和 “downshift” 这两个包。

Combo box 组合框

必须取值于一个预设的可选数据源。

<Autocomplete
  id="combo-box-demo"
  options={top100Films}
  getOptionLabel={(option) => option.title}
  style={{ width: 300 }}
  renderInput={(params) => <TextField {...params} label="Combo box" variant="outlined" />}
/>

练习

以下每个示例演示了自动补全组件的单项功能。

选择一个国家

从248个国家中选择一个。

可控的状态

此组件有两种可控的状态:

  1. “value” 状态(state)包含了 value/onChange 两种属性的组合。 这个状态表示用户选择的值,如当按下 Enter 键时。
  2. “input value” 状态(state) 则包含了 inputValue/onInputChange 两种属性的组合。 这个状态展示了在文本框中显示的值。

⚠️ 以上两种状态互不干涉,它们应该被单独控制着。

value: 'Option 1'
inputValue: ''

Free solo

当将 freeSolo 设置为 true 时,用户可以文本框中输入任意值。

搜索输入栏

该属性的主要使用方式是创建一个带有搜索建议的 输入文本框,例如 Google 搜索 或 react-autowhatever。

Creatable (可创造性)

如果您打算将此模块用于类似 组合框 的体验(一个选择控件元素的增强版),我们则建议如下的设置:

  • selectOnFocus 帮助用户清除所选值。
  • clearOnBlur 帮助用户输入一个新的值。
  • handleHomeEndKeys 使用HomeEnd 键在弹出窗口内移动焦点。
  • 最后一个选项,例如 加上 "你的搜索结果"

您也可以在用户想要加入一个新值的时候显示一个对话框。

分组

<Autocomplete
  id="grouped-demo"
  options={options.sort((a, b) => -b.firstLetter.localeCompare(a.firstLetter))}
  groupBy={(option) => option.firstLetter}
  getOptionLabel={(option) => option.title}
  style={{ width: 300 }}
  renderInput={(params) => <TextField {...params} label="With categories" variant="outlined" />}
/>

失效的选项

<Autocomplete
  id="disabled-options-demo"
  options={timeSlots}
  getOptionDisabled={(option) => option === timeSlots[0] || option === timeSlots[2]}
  style={{ width: 300 }}
  renderInput={(params) => (
    <TextField {...params} label="Disabled options" variant="outlined" />
  )}
/>

useAutocomplete

对于高级定制用例,我们暴露了一个无头(headless)的 useAutocomplete() hook。 它接受几乎与 Autocomplete 组件相同的参数,辅以与 JSX 渲染有关的所有参数。 Autocomplete 组件内部也是使用的此 hook。

import useAutocomplete from '@material-ui/lab/useAutocomplete';

自定义的 hook

请转到 自定义自动完成组件 的部分,来查看使用 Autocomplete 组件(而不是 hook)的例子。

异步请求

Google Maps Places

一个为 Google Maps Places 自动补全功能设计的 UI。

在这个演示中,我们需要加载 [谷歌地图 JavaScript](https://developers. google. com/maps/documentation/javascript/tutorial) 的 API。

⚠️在你开始使用 Google Maps JavaScript API 之前,你必须注册并且创建一个可支付的账户。

多个值

这也称为标签(tags),用户可以输入多个的值。

固定的选项

有时候你需要锁定某个标签,这样他们不会被从界面中移除,这时你可以将 chips 设置为禁用。

Checkboxes 复选框

限制标签数量

当没有聚焦时,你可以使用 limitTags 属性来限制显示选项的数量。

<Autocomplete
  multiple
  limitTags={2}
  id="multiple-limit-tags"
  options={top100Films}
  getOptionLabel={(option) => option.title}
  defaultValue={[top100Films[13], top100Films[12], top100Films[11]]}
  renderInput={(params) => (
    <TextField {...params} variant="outlined" label="limitTags" placeholder="Favorites" />
  )}
/>

尺寸

想要使用外观看起来比较小的输入框吗? 试着使用 size 属性吧。

个性化

自定义输入

使用 renderInput 属性,您可以对输入内容进行自定义渲染。 此 render 属性的第一个参数包含了你想要传递的那些属性。 请特别注意 refinputProps 键(key)。

<Autocomplete
  id="custom-input-demo"
  options={options}
  renderInput={(params) => (
    <div ref={params.InputProps.ref}>
      <input style={{ width: 200 }} type="text" {...params.inputProps} />
    </div>
  )}
/>

GitHub 标签选择器

该演示再现了 GitHub 的标签选择器:

help wanted
type: bug

你也可以转到自定义 hook 章节,查看一下使用 useAutocomplete hook 的自定义例子,而不是使用组件。

高亮显示

以下的例子通过 autosuggest-highlight 这个小型(1 kB)的插件来实现自动推荐和自动补全组件中的高亮文字。

自定义筛选

此组件提供了一个 factory 来构建一个筛选的方法,供给 filterOptions 属性使来用。 用此你可以更改默认的筛选行为。

import { createFilterOptions } from '@material-ui/lab/Autocomplete';

createFilterOptions(config) => filterOptions

参数

  1. config (Object [optional]):
    • config.ignoreAccents (Boolean [optional]):默认值为 true。 移除字母的变音符号。
    • config.ignoreCase (Boolean [optional]): 默认值为true。 所有字母都小写。
    • config.limit (Number [optional]):默认值为 null。 显示限定数量的建议选项。 例如,如果 config.limit100,,那么只显示前 100 个 匹配的选项。 如果存在很多选项匹配,并且虚拟化设置还没建立成时,这样的限制是非常有效的。
    • config.matchFrom ('any' | 'start' [optional]):默认值为 'any'
    • config.stringify (Func [optional]):控制如何将一个选项转换成一个字符串,这样,选项就能够和输入文本的片段相匹配。
    • config.trim (Boolean [optional]):默认值为 false。 删除尾随空格。

返回结果

过滤选项:返回的过滤器方法可以直接提供给 Autocomplete 组件的 filterOptions 属性, 或者可以传给 hook 的同名参数。

在以下的例子中,选项必须有一个查询的前缀:

const filterOptions = createFilterOptions({
  matchFrom: 'start',
  stringify: option => option.title,
});

<Autocomplete filterOptions={filterOptions} />

Advanced 进阶

对于更复杂的过滤机制,譬如模糊匹配(fuzzy matching),我们推荐您看一下 match-sorter。 就像这样:

import matchSorter from 'match-sorter';

const filterOptions = (options, { inputValue }) =>
  matchSorter(options, inputValue);

<Autocomplete filterOptions={filterOptions} />

可视化

在 10000 个随机生成的选项中搜索。 多亏了react-window,这个列表得以可视化。

<Autocomplete
  id="virtualize-demo"
  style={{ width: 300 }}
  disableListWrap
  classes={classes}
  ListboxComponent={ListboxComponent}
  renderGroup={renderGroup}
  options={OPTIONS}
  groupBy={(option) => option[0].toUpperCase()}
  renderInput={(params) => <TextField {...params} variant="outlined" label="10,000 options" />}
  renderOption={(option) => <Typography noWrap>{option}</Typography>}
/>

设计局限

autocomplete/autofill

浏览器会有启发性的帮助用户填写表格。 然而,这样的功能会削弱的组件用户体验。

默认情况下,组件通过 autoComplete="off" 这个属性,禁用了 autocomplete 功能(请注意用户可能在之前已经在给定域输入内容)。

然而,除了记住过去已经输入的值,浏览器可能也会给出 自动填充(autofill) 的建议(譬如有保存的登录信息,地址,或者支付方式等)。 若您不需要自动填充,您可以尝试以下的方式:

  • 给输入框一个不同的名字,这样不会给浏览器泄露任何可以滥用的信息。 例如:id="field1" 而不是 id="country"。 若你不填写 id 的话,该组件则会使用一个随机的 id。
  • 设置为 autoComplete="new-password"
      jsx
      <TextField
      {...params}
      inputProps={{
        ...params.inputProps,
        autoComplete: 'new-password',
      }}
      />

iOS VoiceOver 辅助功能

iOS Safari 中的 VoiceOver 对 aria-owns 属性的支持并不是很到位。 你可以用 disablePortal 属性来解决这个问题。

ListboxComponent

若你提供一共自定义的 ListboxComponent 属性,请保证需要滚动功能的容器将 role 属性设置为 listbox。 这能保证滚动功能在一些情况下,例如当用键盘切换的时候,仍然能够正常显示。

无障碍设计

(WAI-ARIA: https://www.w3.org/TR/wai-aria-practices/#combobox)

我们鼓励用户在 textbox 中使用标签。 组件带入了 WAI-ARIA 授权的一些标准。