用途
多选输入(Multi-select Input)是一种表单组件,允许用户从一组预定义选项中选取多个条目。它与自动补全(Autocomplete)不同:自动补全为自由输入提供建议,而多选输入作用于一个有边界、已知的选项列表,用户只能选择列表中已存在的内容。
最常见的视觉实现是基于标签/芯片(tag/chip)的选择器:已选条目以可移除标签的形式显示在输入框内,剩余选项在下拉列表中展示。其他实现模式还包括复选框列表、双列表(dual listbox)以及原生 <select multiple>。
适用场景
- 分类与标签分配:为内容分配标签、标记或分类。
- 权限与角色管理:为用户选择多个角色。
- 筛选面板:让用户同时应用多个筛选条件。
- 收件人选择:从联系人列表中选择多个邮件收件人。
- 功能选择:配置要启用哪些功能/模块。
不适用场景
- 带建议的自由文本输入:应改用自动补全(Autocomplete)。
- 从少量选项中单选:应改用下拉选择(Select/Dropdown)或单选按钮组(Radio group)。
- 二选一:应改用复选框(Checkboxes)。
- 超大选项集(超过 1000 项):应改用虚拟化列表或以搜索为先的方案。
实现流程
- 在复制示例前,先确认该模式与问题及约束条件匹配。
- 从 references/pattern.md 中的结构与示例入手,选择最小可行的变体。
- 在叠加视觉打磨之前,先应用无障碍、性能和交互方面的防护措施。
- 使用测试指南验证键盘、屏幕阅读器、响应式及失败场景下的行为。
无障碍防护
键盘交互模式:
| 按键 | 操作 |
|---|---|
| Tab | 将焦点移至多选输入;Shift+Tab 反向移动 |
| 下箭头 | 打开下拉列表;向下移动焦点遍历选项 |
| 上箭头 | 向上移动焦点遍历选项 |
| Enter | 选中/取消选中当前聚焦的选项 |
| Space | 选中/取消选中当前聚焦的选项(在列表框中与 Enter 相同) |
| Escape | 关闭下拉列表且不改变选择 |
| Backspace | 当搜索输入为空时,移除最后一个已选标签 |
性能防护
- 下拉打开时间:< 100ms
- 选项过滤(搜索):对于最多 1000 项的列表 < 50ms
- 标签添加渲染:< 16ms(一帧)
- 全选操作:对于 100 项 < 50ms
- 每个实例内存:组件 < 15KB;选项超过 500 项时对选项列表进行虚拟化
常见错误
使用 <select multiple>
问题:原生 <select multiple> 需要 Ctrl+Click(或 Cmd+Click)才能多选,这是一种大多数用户并不知晓的、不直观的交互。
<!-- Bad: Requires Ctrl+click — users don't know this -->
<select multiple name="skills[]">
<option>React</option>
<option>TypeScript</option>
</select>
修复方式:使用带复选框或基于标签 UI 的自定义多选组件。
每次选择后关闭下拉列表
问题:如果用户每选一项下拉列表就关闭,他们必须为每个额外选择重新打开它,这会显著拖慢多选工作流。
修复方式:选择后保持下拉列表打开;仅在 Escape 或外部点击时关闭。
option.addEventListener('click', (e) => {
e.stopPropagation(); // Prevent close-on-outside-click from triggering
toggleOptionSelection(option);
updateTags();
searchInput.focus(); // Keep focus in the input
// DO NOT close the dropdown here
});
未处理 Backspace 移除标签
问题:用户期望在空搜索输入中按 Backspace 能移除最后一个已选标签。缺少此功能会让组件显得不完整,并迫使用户使用鼠标。
修复方式:监听搜索输入上的 keydown 事件。
searchInput.addEventListener('keydown', (e) => {
if (e.key === 'Backspace' && searchInput.value === '') {
const lastTag = getLastSelectedItem();
if (lastTag) {
removeSelection(lastTag);
}
}
});
相关模式
- https://uxpatterns.dev/patterns/forms/autocomplete
- https://uxpatterns.dev/patterns/forms/checkbox
- https://uxpatterns.dev/patterns/forms/radio
- https://uxpatterns.dev/patterns/forms/selection-input
完整实现细节、示例和测试说明,请参见 references/pattern.md。
模式页面:https://uxpatterns.dev/patterns/forms/multi-select-input