Reka UI 徽标Reka
backdrop
组件

列表框

一种允许用户在选中和未选中之间切换的控件。
水果
苹果
香蕉
蓝莓
葡萄
菠萝
蔬菜
茄子
西兰花
胡萝卜
西葫芦
韭葱

功能

  • 可受控或不受控。
  • 支持项、标签、项组。
  • 焦点完全受控。
  • 完整的键盘导航。
  • 支持从右到左的方向。
  • 不同的选择行为。

安装

从命令行安装此组件。

sh
$ npm add reka-ui

结构

导入所有部分并将其组合。

vue
<script setup>
import { ListboxContent, ListboxFilter, ListboxGroup, ListboxGroupLabel, ListboxItem, ListboxItemIndicator, ListboxRoot, ListboxVirtualizer } from 'reka-ui'
</script>

<template>
  <ListboxRoot>
    <ListboxFilter />

    <ListboxContent>
      <ListboxItem>
        <ListboxItemIndicator />
      </ListboxItem>

      <!-- or with group -->
      <ListboxGroup>
        <ListboxGroupLabel />
        <ListboxItem>
          <ListboxItemIndicator />
        </ListboxItem>
      </ListboxGroup>

      <!-- or with virtual -->
      <ListboxVirtualizer>
        <ListboxItem>
          <ListboxItemIndicator />
        </ListboxItem>
      </ListboxVirtualizer>
    </ListboxContent>
  </ListboxRoot>
</template>

API 参考

包含列表框的所有部分。在 form 中使用时,还将渲染一个 input 以确保事件正确传播。

属性默认类型
as
'div'
AsTag | 组件

此组件应渲染为的元素或组件。可通过 asChild 覆盖。

asChild
布尔值

更改默认渲染元素为作为子项传递的元素,合并它们的属性和行为。

阅读我们的 组合指南了解更多详情。

by
string | ((a: AcceptableValue, b: AcceptableValue) => boolean)

使用此项可通过特定字段比较对象,或传入您自己的比较函数以完全控制对象的比较方式。

defaultValue
AcceptableValue | AcceptableValue[]

列表框初始渲染时的值。当您不需要控制列表框状态时使用此项。

dir
'ltr' | 'rtl'

列表框的阅读方向(适用时)。
如果省略,则全局继承自 ConfigProvider 或假定为 LTR(从左到右)阅读模式。

disabled
布尔值

当为 true 时,阻止用户与列表框交互。

highlightOnHover
布尔值

当为 true 时,鼠标悬停在项目上会触发高亮显示。

modelValue
AcceptableValue | AcceptableValue[]

列表框的受控值。可与 v-model 绑定。

multiple
布尔值

是否可以选择多个选项。

name
string

字段的名称。随其所属的表单一起作为名称/值对提交。

orientation
'vertical'
'vertical' | 'horizontal'

列表框的方向。
主要是为了相应地进行箭头导航(左右 vs. 上下)。

required
布尔值

当为 true 时,表示用户必须在所属表单提交前设置值。

selectionBehavior
'toggle'
'toggle' | 'replace'

集合中多选行为的方式。

事件触发载荷
entryFocus
[event: CustomEvent<any>]

容器获得焦点时调用的事件处理程序。可阻止其默认行为。

highlight
[payload: { ref: HTMLElement; value: AcceptableValue; }]

高亮元素改变时的事件处理程序。

leave
[事件: Event]

鼠标离开容器时调用的事件处理程序。

update:modelValue
[value: AcceptableValue]

值改变时调用的事件处理程序。

插槽(默认)载荷
modelValue
AcceptableValue | AcceptableValue[] | undefined

当前活动值

数据属性
[data-disabled]禁用时存在

筛选

用于执行筛选的输入元素。

属性默认类型
as
'input'
AsTag | 组件

此组件应渲染为的元素或组件。可通过 asChild 覆盖。

asChild
布尔值

更改默认渲染元素为作为子项传递的元素,合并它们的属性和行为。

阅读我们的 组合指南了解更多详情。

autoFocus
布尔值

挂载时聚焦元素。

disabled
布尔值

当为 true 时,阻止用户与项目交互

modelValue
string

筛选器的受控值。可与 v-model 绑定。

事件触发载荷
update:modelValue
[string]

值改变时调用的事件处理程序。

插槽(默认)载荷
modelValue
string | undefined

当前输入值

数据属性
[data-disabled]禁用时存在

内容

包含所有列表框组和项。

属性默认类型
as
'div'
AsTag | 组件

此组件应渲染为的元素或组件。可通过 asChild 覆盖。

asChild
布尔值

更改默认渲染元素为作为子项传递的元素,合并它们的属性和行为。

阅读我们的 组合指南了解更多详情。

项组件。

属性默认类型
as
'div'
AsTag | 组件

此组件应渲染为的元素或组件。可通过 asChild 覆盖。

asChild
布尔值

更改默认渲染元素为作为子项传递的元素,合并它们的属性和行为。

阅读我们的 组合指南了解更多详情。

disabled
布尔值

当为 true 时,阻止用户与项目交互。

值*
AcceptableValue

与 `name` 一起提交时作为数据给出的值。

事件触发载荷
select
[event: SelectEvent<AcceptableValue>]

选择项时调用的事件处理程序。
可以通过调用 event.preventDefault 来阻止它。

数据属性
[data-state]"选中" | "未选中"
[data-highlighted]高亮时存在
[data-disabled]禁用时存在

项指示器

当项目被选中时渲染。您可以直接设置此元素的样式,或者将其用作包装器以放入图标,或两者兼而有之。

属性默认类型
as
'span'
AsTag | 组件

此组件应渲染为的元素或组件。可通过 asChild 覆盖。

asChild
布尔值

更改默认渲染元素为作为子项传递的元素,合并它们的属性和行为。

阅读我们的 组合指南了解更多详情。

用于分组多个项。与 ListboxGroupLabel 结合使用可确保通过自动标签实现良好的可访问性。

属性默认类型
as
'div'
AsTag | 组件

此组件应渲染为的元素或组件。可通过 asChild 覆盖。

asChild
布尔值

更改默认渲染元素为作为子项传递的元素,合并它们的属性和行为。

阅读我们的 组合指南了解更多详情。

组标签

用于渲染组的标签。它无法通过箭头键聚焦。

属性默认类型
as
'div'
AsTag | 组件

此组件应渲染为的元素或组件。可通过 asChild 覆盖。

asChild
布尔值

更改默认渲染元素为作为子项传递的元素,合并它们的属性和行为。

阅读我们的 组合指南了解更多详情。

for
string

虚拟化器

用于实现列表虚拟化的虚拟容器。

属性默认类型
estimateSize
数字

每个项的估计大小(以像素为单位)

options*
AcceptableValue[]

项目列表

overscan
数字

在可见区域之外渲染的项目数量

textContent
((option: AcceptableValue) => string)

每个项的文本内容,以实现预输入功能

插槽(默认)载荷
option
null | string | number | bigint | Record<string, any>
virtualizer
Virtualizer<HTMLElement, Element>
virtualItem
VirtualItem

示例

将对象绑定为值

与仅允许将字符串作为值的原生 HTML 表单控件不同,reka-ui 也支持绑定复杂对象。

vue
<script setup lang="ts">
import { ListboxContent, ListboxFilter, ListboxItem, ListboxRoot } from 'reka-ui'
import { ref } from 'vue'

const people = [
  { id: 1, name: 'Durward Reynolds' },
  { id: 2, name: 'Kenton Towne' },
  { id: 3, name: 'Therese Wunsch' },
  { id: 4, name: 'Benedict Kessler' },
  { id: 5, name: 'Katelyn Rohan' },
]
const selectedPeople = ref(people[0])
</script>

<template>
  <ListboxRoot v-model="selectedPeople">
    <ListboxContent>
      <ListboxItem
        v-for="person in people"
        :key="person.id"
        :value="person"
        :disabled="person.unavailable"
      >
        {{ person.name }}
      </ListboxItem>
    </ListboxContent>
  </ListboxRoot>
</template>

选择多个值

Listbox 组件允许您选择多个值。您可以通过提供一个值数组而不是单个值来启用此功能。

vue
<script setup lang="ts">
import { ListboxRoot } from 'reka-ui'
import { ref } from 'vue'

const people = [
  { id: 1, name: 'Durward Reynolds' },
  { id: 2, name: 'Kenton Towne' },
  { id: 3, name: 'Therese Wunsch' },
  { id: 4, name: 'Benedict Kessler' },
  { id: 5, name: 'Katelyn Rohan' },
]
const selectedPeople = ref([people[0], people[1]])
</script>

<template>
  <ListboxRoot
    v-model="selectedPeople"
    multiple
  >
    ...
  </ListboxRoot>
</template>

自定义筛选

vue
<script setup lang="ts">
import { ListboxContent, ListboxFilter, ListboxItem, ListboxRoot, useFilter } from 'reka-ui'
import { ref } from 'vue'

const people = [
  { id: 1, name: 'Durward Reynolds' },
  { id: 2, name: 'Kenton Towne' },
  { id: 3, name: 'Therese Wunsch' },
  { id: 4, name: 'Benedict Kessler' },
  { id: 5, name: 'Katelyn Rohan' },
]
const selectedPeople = ref(people[0])
const searchTerm = ref('')

const { startsWith } = useFilter({ sensitivity: 'base' })
const filteredPeople = computed(() => people.filter(p => startsWith(p.name, searchTerm.value)))
</script>

<template>
  <ListboxRoot v-model="selectedPeople">
    <ListboxFilter v-model="searchTerm" />
    <ListboxContent>
      <ListboxItem
        v-for="person in filteredPeople"
        :key="person.id"
        :value="person"
      >
        {{ person.name }}
      </ListboxItem>
    </ListboxContent>
  </ListboxRoot>
</template>

虚拟列表

渲染长列表项可能会降低应用程序速度,因此使用虚拟化可以显著提高性能。

有关虚拟化的更多通用信息,请参阅虚拟化指南

vue
<script setup lang="ts">
import { ListboxContent, ListboxFilter, ListboxItem, ListboxRoot, ListboxVirtualizer } from 'reka-ui'
import { ref } from 'vue'

const people = [
  { id: 1, name: 'Durward Reynolds' },
  { id: 2, name: 'Kenton Towne' },
  { id: 3, name: 'Therese Wunsch' },
  { id: 4, name: 'Benedict Kessler' },
  { id: 5, name: 'Katelyn Rohan' },
  // and a lot more
]
</script>

<template>
  <ListboxRoot>
    <ListboxContent>
      <ListboxVirtualizer
        v-slot="{ option }"
        :options="people"
        :text-content="(opt) => opt.name"
      >
        <ListboxItem :value="option">
          {{ person.name }}
        </ListboxItem>
      </ListboxVirtualizer>
    </ListboxContent>
  </ListboxRoot>
</template>

可访问性

遵循 列表框 WAI-ARIA 设计模式

键盘交互

描述
回车键
ListboxItem 高亮时,选择聚焦的项目。
向下箭头键
当焦点在 ListboxItem 上时,将焦点移到下一个项目。
向上箭头键
当焦点在 ListboxItem 上时,将焦点移到上一个项目。
Home
将焦点和高亮移动到第一个项目。
End
将焦点和高亮移动到最后一个项目。
Ctrl/Cmd + A
选择所有项目。