Autocomplete 自动补全组件
自动补全是一个普通文本输入框,它通过一组建议的选项来帮助用户输入。
该组件常用于以下两个场景中的单行文本框赋值:
- 文本框必须取值于某个预设好的,例如:一个位置域必须包含一个有效的位置名称: 组合框。
- 文本框也可以是任何值,但最好能够为用户提供可能的选项,譬如搜索框可以提供近似的或者曾搜索过的选项以节省用户时间:灵活的单文本框。
此组件旨在改进 “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" />}
/>
可控的状态
此组件有两种可控的状态:
- 一种状态是“value”,它是
value
/onChange
属性的组合。 - 还有一种状态是 “input value”,它则是
inputValue
/onInputChange
这两个属性的组合。
⚠️ 以上两种状态互不干涉,它们应该被单独控制着。
免费工具
将 freeSolo
设置为true,以便在文本框中输入任意值。 Prop的设计是为了覆盖搜索框的主要用例,并提出建议,例如谷歌搜索。
然而,仍然存在着这种情况。 如果您打算将它用于一个 组合框 (一个强化的选定元素版本),我们建议设置 selectOnFocus
(它帮助用户清除选定的值)。
您也可以在用户想要添加一个新的值时显示一个对话框。
<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
对于那些更高级的定制用例,我们公开了一个 useAutocomplete()
hook。 它接受的参数与 Autocomplete 组件接受的大同小异,但是不包括与 JSX 渲染相关的所有属性。 Autocomplete 组件的内部也使用了此 hook。
import useAutocomplete from '@material-ui/lab/useAutocomplete';
- 📦 4.5kB 的压缩包。
你也可以转到定制的自动补全组件章节,查看一下使用 自动补全(Autocomplete)
组件的自定义例子,而不是使用 hook。
异步请求
在这个例子里,我们加载了[Google Maps JavaScript](https://developers. google. com/maps/documentation/javascript/tutorial) API。
⚠️在你开始使用 Google Maps JavaScript API 之前,你必须注册并且创建一个可支付的账户。
多个值
这也称为标签,允许用户输入多个值。
<Autocomplete
multiple
id="fixed-tags-demo"
options={top100Films}
getOptionLabel={(option) => option.title}
defaultValue={[top100Films[6], top100Films[13]]}
renderTags={(value, getTagProps) =>
value.map((option, index) => (
<Chip label={option.title} {...getTagProps({ index })} disabled={index === 0} />
))
}
style={{ width: 500 }}
renderInput={(params) => (
<TextField {...params} label="Fixed tag" variant="outlined" placeholder="Favorites" />
)}
/>
<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" />
)}
/>
你也可以转到自定义 hook 章节,查看一下使用 useAutocomplete
hook 的自定义例子,而不是使用自动补全组件(Autocomplete)。
高亮显示
以下的例子通过 autosuggest-highlight 这个小型(1 kB)的插件来实现自动推荐和自动补全组件中的高亮文字。
自定义筛选
此组件提供了一个工厂来构建一个筛选的方法,供给 filerOption
属性使用。 用此你可以更改默认的筛选行为。
import { createFilterOptions } from '@material-ui/lab/Autocomplete';
createFilterOptions(config) => filterOptions
参数
config
(Object [optional]):config.ignoreAccents
(Boolean [optional]): 默认值为true
。 移除字母的变音符号。config.ignoreCase
(Boolean [optional]): 默认值为true
。 所有字母都小写。config.limit
(Number [optional]): 默认值为 null。 显示限定数量的建议选项。 譬如,如果config.limit
为100
,那么只显示前100
个匹配的选项。 如果存在很多选项匹配,并且虚拟化设置还没建立成时,这样的限制是非常有效的。config.matchFrom
('any' | 'start' [optional]): 默认值为'any'
。config.startAfter
(Number [optional]): 默认值为0
。 只在定量的字母之后显示建议选项。config.stringify
(Func [optional]): Controls how an option is converted into a string so that it can be matched against the input text fragment.config.trim
(Boolean [optional]): 默认值为false
。 Remove trailing spaces.
返回结果
filterOptions
: the returned filter method can be provided directly to the filterOptions
prop of the Autocomplete
component, or the parameter of the same name for the hook.
In the following demo, the options need to start with the query prefix:
const filterOptions = createFilterOptions({
matchFrom: 'start',
stringify: option => option.title,
});
<Autocomplete filterOptions={filterOptions} />
高级
For richer filtering mechanisms, like fuzzy matching, it's recommended to look at match-sorter. 就像这样:
import matchSorter from 'match-sorter';
const filterOptions = (options, { inputValue }) =>
matchSorter(options, inputValue);
<Autocomplete filterOptions={filterOptions} />
虚拟滚动
Search within 10,000 randomly generated options. The list is virtualized thanks to 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
The browsers have heuristics to help the users fill the form inputs. However, it can harm the UX of the component.
By default, the component disable the autocomplete feature (remembering what the user has typed for a given field in a previous session) with the autoComplete="off"
attribute.
However, in addition to remembering past entered values, the browser might also propose autofill suggestions (saved login, address, or payment details). In the event you want the avoid autofill, you can try the following:
- Name the input without leaking any information the browser can use. e.g.
id="field1"
instead ofid="country"
. If you leave the id empty, the component uses a random id. - Set
autoComplete="new-password"
:jsx <TextField {...params} inputProps={{ ...params.inputProps, autoComplete: 'new-password', }} />
iOS VoiceOver
VoiceOver on iOS Safari doesn't support the aria-owns
attribute very well. You can work around the issue with the disablePortal
prop.
TypeScript
To fully take advantage of type inference, you need to set the multiple
prop to undefined
, false
or true
. See this discussion for more details. TypeScript might solve this bug in the future.
ListboxComponent
If you provide a custom ListboxComponent
prop, you need to make sure that the intended scroll container has the role
attribute set to listbox
. This ensures the correct behavior of the scroll, for example when using the keyboard to navigate.
可访问性
(WAI-ARIA: https://www.w3.org/TR/wai-aria-practices/#combobox)
We encourage the usage of a label for the textbox. The component implements the WAI-ARIA authoring practices.