跳到内容
+

自动完成

自动完成组件是由建议选项面板增强的文本输入框。

简介

自动完成组件是一个增强的文本输入框,它在用户输入时显示建议选项列表,并允许用户从列表中选择一个选项。

MUI Base 提供了 useAutocomplete 钩子,用于构建自定义自动完成功能。它实现了 WAI-ARIA Combobox 模式,通常用于帮助用户更快地完成表单输入或搜索查询。

钩子

import { useAutocomplete } from '@mui/base/useAutocomplete';

useAutocomplete 钩子需要一个 options 列表,以便在文本框获得焦点时显示。该值必须从预定义的集合中选择。

以下演示展示了如何创建一个简单的组合框,应用样式,并使用 onChange 属性将选定的值写入状态变量

Enter 开始编辑

自定义

渲染选项

默认情况下,options 属性接受 string{ label: string } 数组

const options = [
  { label: 'The Godfather', id: 1 },
  { label: 'Pulp Fiction', id: 2 },
];
// or
const options = ['The Godfather', 'Pulp Fiction'];

如果您需要为选项使用不同的结构,您必须为 getOptionLabel 属性提供一个函数,该函数将每个选项解析为一个唯一值。

const options = [
  { issuer: 'Bank of America', brand: 'Visa', last4: '1234' },
  { issuer: 'Bank of America', brand: 'MasterCard', last4: '5678' },
  { issuer: 'Barclays', brand: 'Visa', last4: '4698' },
  // ...
];

const {
  getRootProps,
  // etc
} = useAutocomplete({
  getOptionLabel: (option) => option.last4,
});

受控状态

useAutocomplete 钩子有两个可以控制的状态

  1. “value”状态,使用 value/onChange 属性组合。此状态表示用户选择的值,例如在按下 Enter 时。
  2. “input value”状态,使用 inputValue/onInputChange 属性组合。此状态表示文本框中显示的值。

这两个状态是隔离的,应该独立控制。

value: Firefox
inputValue: 

使用 portal

React Portal 可用于在 DOM 层次结构之外渲染列表框,使其更容易“浮动”在相邻元素之上。

MUI Base 提供了一个围绕 React 的 createPortal() 构建的 Popper 组件,正是为了这个目的,并且还可以帮助您管理键盘焦点,因为它在 portal 中和 portal 外移动。

要在 MUI Base 的 Popper 中渲染列表框,必须按如下方式合并 ref

import { useAutocomplete } from '@mui/base/useAutocomplete';
import { Popper } from '@mui/base/Popper';
import { unstable_useForkRef as useForkRef } from '@mui/utils';

export default function App(props) {
  const {
    getRootProps,
    getInputProps,
    getListboxProps,
    getOptionProps,
    popupOpen,
    anchorEl,
    setAnchorEl,
    groupedOptions,
  } = useAutocomplete(props);

  const rootRef = useForkRef(ref, setAnchorEl);

  return (
    <React.Fragment>
      <div {...getRootProps()} ref={rootRef}>
        <input {...getInputProps()} />
      </div>
      {anchorEl && (
        <Popper open={popupOpen} anchorEl={anchorEl}>
          {groupedOptions.length > 0 && (
            <ul {...getListboxProps()}>
              {groupedOptions.map((option, index) => (
                <li {...getOptionProps({ option, index })}>{option.label}</li>
              ))}
            </ul>
          )}
        </Popper>
      )}
    </React.Fragment>
  );
}

这是一个完整的演示,展示了如何在 Popper 内部渲染列表框