命令面板
概述
用于快速搜索与执行命令的命令面板组件。SCommand 是基于 Aria listbox 基础组件与 Fuse 模糊匹配构建的可搜索命令面板。它把过滤、分组条目聚合与默认条目组合逻辑委托给 Aria CommandCompact;UI 包装组件只注入样式。
命令面板适合 ⌘K 式面板、可搜索菜单或内联类型过滤。普通操作菜单请用 dropdown-menu;紧凑单选列表请用 select。
用法
SCommand现在会把过滤、分组条目聚合与默认条目组合逻辑委托给 AriaCommandCompact。如果需要无样式、数据驱动的组合入口,可从@vean/aria/command直接导入CommandCompact。
特性
- 🔎 模糊搜索 — 基于 Fuse 对
label/groupLabel/description匹配,fuseOptions可配置(threshold、resultLimit、空搜索全匹配) - 🧩 Aria/样式分离 —
CommandCompact负责过滤、分组与条目组合;SCommand只注入样式 - 📊 分组数据 —
items支持嵌套组items(label/value/icon/description/disabled/separator)与扁平条目 - 🔍 条目描述 —
description在标签下方渲染为次级文本,并参与内置过滤 - 🚀 外部过滤 —
external-filter跳过内置模糊过滤,让 items 由外部引擎(如全文内容搜索)过滤与排序 - ⌨️ 键盘导航 — 完整 listbox roving focus(方向键)、选择与
highlight/select事件 - 🏷️ 图标 + 快捷键 — 每项
icon与shortcut(渲染为Kbd) - 🧹 可清空 —
clearable显示尾部清空控件;placeholder/emptyLabel本地化空态 - 🔒 禁用 —
disabled禁用输入并阻止选择 - ♿ 无障碍 —
role="listbox"/option、带aria-label的列表、带标签的输入、axe-core零违规
组件家族
SCommand(样式层)— 入口包装组件;commandVariants配方配合动态插槽转发CommandCompact(Aria)— 聚合组件;负责搜索、分组、过滤与默认条目组合ListboxRoot/ListboxFilter/ListboxContent/ListboxGroup/ListboxGroupLabel/ListboxItem(Aria)— 底层 listbox 基础组件Kbd(Aria)— 渲染条目shortcut
演示
基础
对话框
API
Aria 层
8Command<T>
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
class | ClassValue | — | 根类。 |
size | ThemeSize | — | 组件的视觉尺寸。 |
ui | Partial<CommandUi> | — | 该组件的按槽类重写。 |
items | CommandOptionData<T>[] | — | 由该组件渲染的项。 |
placeholder | string | — | 占位符。 |
searchTerm | string | — | 搜索词。 |
externalFilter | boolean | — | 项目是否已由外部引擎进行过滤和排序
(例如全文内容搜索)。当为 true 时,将跳过内置的模糊过滤器,
所有 `items` 将按原样渲染;`searchTerm` 仍通过
`update:searchTerm` 进行同步,以便调用方可自行驱动搜索。 |
clearable | boolean | — | 是否可清除。 |
fuseOptions | UseFuseOptions<T> | — | Fuse 选项。 |
listProps | ListboxContentProps | — | 转发给列表元素的属性。 |
itemProps | ListboxItemProps | — | 转发给 item 元素的属性。 |
itemLabelProps | CommandItemLabelProps | — | 传递给 item label 元素的属性。 |
itemContentProps | CommandItemContentProps | — | 这些属性将传递给 item content 元素(包含 label 和 description)。 |
itemDescriptionProps | CommandDescriptionProps | — | 传递给项描述元素的属性。 |
groupProps | ListboxGroupProps | — | 转发给 group 元素的属性。 |
groupLabelProps | ListboxGroupLabelProps | — | 转发至组标签元素的属性。 |
shortcutProps | CommandShortcutProps | — | 转发给快捷方式元素的属性。 |
separatorProps | CommandSeparatorProps | — | 转发给分隔符元素的属性。 |
inputProps | ListboxFilterProps | — | 转发给输入元素的属性。 |
emptyProps | CommandEmptyProps | — | 转发给空元素的属性。 |
emptyLabel | string | — | 空标签。 |
modelValue | string | — | 所选项的受控值。
当需要控制项的状态时使用此属性。可通过 `v-model` 进行绑定。 |
defaultValue | string | — | 所选项的默认值。
当需要设置项的初始状态时,请使用此选项。 |
multiple | false | — | 用于确定一次可选择“单个”还是“多个”项目。
此属性将覆盖根据 `modelValue` 和 `defaultValue` 推断出的类型。 |
selectionBehavior | SelectionBehavior | 'toggle' | 集合中多选功能应如何工作。 |
disabled | boolean | — | 当值为 `true` 时,禁止用户与列表框进行交互 |
dir | Direction | — | 列表框的阅读方向(如适用)。<br> 若省略,则从全局 `ConfigProvider` 继承,或
默认采用 LTR(从左到右)阅读模式。 |
orientation | DataOrientation | — | 列表框的方向。<br>主要是为了确保箭头导航方向与之对应(左右 vs. 上下) |
name | string | — | 字段的名称。作为名称/值对的一部分,与其所属表单一同提交。 |
highlightOnHover | boolean | — | 当值为 `true` 时,将鼠标悬停在项目上会触发高亮显示 |
required | boolean | — | 当值为 `true` 时,表示用户必须先设置该值,所属表单才能提交。 |
事件
| 事件名 | 参数 | 描述 |
|---|---|---|
update:modelValue | string | — |
highlight | CollectionItemData<ListboxCollectionItemData> | undefined | 当选中元素发生变化时的事件处理程序。 |
entryFocus | CustomEvent<any> | 当容器获得焦点时触发的事件处理程序。可被阻止。 |
leave | Event | 当鼠标离开容器时调用的事件处理程序 |
select | SelectEvent<string> | 当选中某项时触发的事件处理程序。<br> 可以通过调用 `event.preventDefault` 来阻止该事件。 |
update:searchTerm | string | 当搜索词的值发生变化时触发。 |
插槽
| 插槽名 | 参数 | 描述 |
|---|---|---|
input-leading | CommandCompactInputSlotProps | 输入首槽的自定义内容。 |
input-trailing | CommandCompactInputSlotProps | 输入末尾槽位的自定义内容。 |
empty | — | 为空槽位添加自定义内容。 |
item-leading | CommandCompactItemSlotProps<T> | 用于项目引导槽位的自定义内容。 |
item-trailing | CommandCompactItemSlotProps<T> | 用于项目尾部槽位的自定义内容。 |
item-label | CommandCompactItemSlotProps<T> | 针对项目标签插槽的自定义内容。 |
item-description | CommandCompactItemSlotProps<T> | 项目描述字段的自定义内容。 |
bottom | — | 底部区域的自定义内容。 |
CommandCompact<T>
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
items | CommandOptionData<T>[] | — | 由该组件渲染的项。 |
placeholder | string | — | 占位符。 |
searchTerm | string | — | 搜索词。 |
externalFilter | boolean | — | 项目是否已由外部引擎进行过滤和排序
(例如全文内容搜索)。当为 true 时,将跳过内置的模糊过滤器,
所有 `items` 将按原样渲染;`searchTerm` 仍通过
`update:searchTerm` 进行同步,以便调用方可自行驱动搜索。 |
clearable | boolean | — | 是否可清除。 |
fuseOptions | UseFuseOptions<T> | — | Fuse 选项。 |
listProps | ListboxContentProps | — | 转发给列表元素的属性。 |
itemProps | ListboxItemProps | — | 转发给 item 元素的属性。 |
itemLabelProps | CommandItemLabelProps | — | 传递给 item label 元素的属性。 |
itemContentProps | CommandItemContentProps | — | 这些属性将传递给 item content 元素(包含 label 和 description)。 |
itemDescriptionProps | CommandDescriptionProps | — | 传递给项描述元素的属性。 |
groupProps | ListboxGroupProps | — | 转发给 group 元素的属性。 |
groupLabelProps | ListboxGroupLabelProps | — | 转发至组标签元素的属性。 |
shortcutProps | CommandShortcutProps | — | 转发给快捷方式元素的属性。 |
separatorProps | CommandSeparatorProps | — | 转发给分隔符元素的属性。 |
inputProps | ListboxFilterProps | — | 转发给输入元素的属性。 |
emptyProps | CommandEmptyProps | — | 转发给空元素的属性。 |
emptyLabel | string | — | 空标签。 |
modelValue | string | — | 所选项的受控值。
当需要控制项的状态时使用此属性。可通过 `v-model` 进行绑定。 |
defaultValue | string | — | 所选项的默认值。
当需要设置项的初始状态时,请使用此选项。 |
multiple | false | — | 用于确定一次可选择“单个”还是“多个”项目。
此属性将覆盖根据 `modelValue` 和 `defaultValue` 推断出的类型。 |
selectionBehavior | SelectionBehavior | 'toggle' | 集合中多选功能应如何工作。 |
disabled | boolean | — | 当值为 `true` 时,禁止用户与列表框进行交互 |
dir | Direction | — | 列表框的阅读方向(如适用)。<br> 若省略,则从全局 `ConfigProvider` 继承,或
默认采用 LTR(从左到右)阅读模式。 |
orientation | DataOrientation | — | 列表框的方向。<br>主要是为了确保箭头导航方向与之对应(左右 vs. 上下) |
name | string | — | 字段的名称。作为名称/值对的一部分,与其所属表单一同提交。 |
highlightOnHover | boolean | — | 当值为 `true` 时,将鼠标悬停在项目上会触发高亮显示 |
required | boolean | — | 当值为 `true` 时,表示用户必须先设置该值,所属表单才能提交。 |
事件
| 事件名 | 参数 | 描述 |
|---|---|---|
update:modelValue | string | — |
highlight | CollectionItemData<ListboxCollectionItemData> | undefined | 当选中元素发生变化时的事件处理程序。 |
entryFocus | CustomEvent<any> | 当容器获得焦点时触发的事件处理程序。可被阻止。 |
leave | Event | 当鼠标离开容器时调用的事件处理程序 |
select | SelectEvent<string> | 当选中某项时触发的事件处理程序。<br> 可以通过调用 `event.preventDefault` 来阻止该事件。 |
update:searchTerm | string | 当搜索词的值发生变化时触发。 |
插槽
| 插槽名 | 参数 | 描述 |
|---|---|---|
input-leading | CommandCompactInputSlotProps | 输入首槽的自定义内容。 |
input-trailing | CommandCompactInputSlotProps | 输入末尾槽位的自定义内容。 |
empty | — | 为空槽位添加自定义内容。 |
item-leading | CommandCompactItemSlotProps<T> | 用于项目引导槽位的自定义内容。 |
item-trailing | CommandCompactItemSlotProps<T> | 用于项目尾部槽位的自定义内容。 |
item-label | CommandCompactItemSlotProps<T> | 针对项目标签插槽的自定义内容。 |
item-description | CommandCompactItemSlotProps<T> | 项目描述字段的自定义内容。 |
bottom | — | 底部区域的自定义内容。 |
CommandDescription
CommandEmpty
CommandItemContent
CommandItemLabel
CommandSeparator
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
orientation | DataOrientation | — | 组件的排列方向。
可选值为 `vertical` 或 `horizontal`。默认值为 `horizontal`。 |
decorative | boolean | — | 该组件是否纯属装饰性。<br>当值为 `true` 时,将更新与无障碍相关的属性,
从而将渲染后的元素从无障碍树中移除。 |
CommandShortcut
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
symbolize | boolean | true | 是否将命令值转换为符号表示形式。 |
注意事项
架构与对标差异
CommandCompact 负责 Fuse 搜索、分组条目聚合与默认条目组合,底层 listbox 基础组件保持零样式,仅由 UI 包装组件注入 commandVariants 类。这与 cmdk/shadcn-ui 的 headless command 分离一致。Ant Design、Element Plus、Mantine、Naive UI 提供 select/autocomplete 而非专用命令面板;VeanUI 提供真正的 ⌘K 式命令面板,带 Fuse 模糊搜索、分组数据、图标/快捷键与完整 listbox 键盘行为。
| 能力 | VeanUI | shadcn/ui (cmdk) | Ant Design | Element Plus | Mantine | Naive UI |
|---|---|---|---|---|---|---|
| Aria/样式分离 | ✅ | ✅ | — | — | — | — |
| 模糊搜索(Fuse) | ✅ | ✅ | — | — | — | — |
| 分组数据 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| 图标 + 快捷键 | ✅ | ✅ | — | — | ✅ | — |
| 键盘导航 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| 空态 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
— = 不支持或采用不同交互模型。
运行时注意
searchTerm可用v-model:searchTerm控制;过滤由 Fuse 执行(默认threshold: 0.1、resultLimit: 12、空搜索全匹配)。items接受分组对象(嵌套items)与扁平条目;separator: true在组/条目后渲染分隔线。shortcut渲染为Kbd(如['command', 'h']);icon渲染前导图标。clearable显示尾部清空控件,重置searchTerm;空态使用本地化command.noResults消息。- 底层 listbox 处理键盘/roving focus;选择发出
select与update:modelValue。
Roadmap
不适用——command 对当前对标集已功能完备。
FAQ
如何构建命令面板?
传入 items 与 placeholder:
<SCommand
placeholder="输入命令..."
:items="[
{ label: '搜索 Emoji', value: 'emoji', icon: 'lucide:smile' },
{ label: '帮助', value: 'help', icon: 'lucide:help-circle', shortcut: ['command', 'h'] }
]"
@select="onSelect"
/>如何分组条目?
在分组对象下嵌套 items 并加 separator:
<SCommand
:items="[
{
label: '建议',
value: 'suggestions',
separator: true,
items: [{ label: '日历', value: 'calendar' }]
}
]"
/>如何控制搜索词?
用 v-model:searchTerm 绑定 searchTerm 并调整 fuse-options:
<SCommand v-model:searchTerm="query" :items="items" :fuse-options="{ threshold: 0.3 }" />如何显示空态?
设置 empty-label(回退到本地化 command.noResults):
<SCommand :items="items" empty-label="未找到结果" />如何处理选择?
监听 select 与 update:modelValue:
<SCommand :items="items" @select="value => run(value)" />如何显示条目描述?
给条目加 description——它会在标签下方渲染为次级文本,并参与内置模糊过滤:
<SCommand :items="[{ label: '日历', value: 'calendar', description: '日程管理视图' }]" />如何用外部搜索引擎代替内置过滤?
设置 external-filter:跳过内置模糊过滤,items 原样渲染(保留你自己的排序)。searchTerm 仍通过 v-model:searchTerm / update:searchTerm 同步,供你驱动自己的搜索——例如全文内容搜索:
<SCommand v-model:searchTerm="query" external-filter :items="results" @select="open" />