列表框
<script setup lang="ts">
import { Icon } from '@iconify/vue'
import { ListboxContent, ListboxGroup, ListboxGroupLabel, ListboxItem, ListboxItemIndicator, ListboxRoot } from 'radix-vue'
const fruits = ['Apple', 'Banana', 'Blueberry', 'Grapes', 'Pineapple']
const vegetables = ['Aubergine', 'Broccoli', 'Carrot', 'Courgette', 'Leek']
</script>
<template>
<ListboxRoot class=" flex flex-col rounded-lg border bg-white text-green9 mx-auto ">
<ListboxContent class="p-[5px] w-48 h-72 overflow-auto">
<ListboxGroup>
<ListboxGroupLabel class="px-[25px] text-xs leading-[25px] text-mauve11">
Fruits
</ListboxGroupLabel>
<ListboxItem
v-for="i in fruits"
:key="i"
:value="i"
class="w-full flex items-center px-[25px] h-[25px] leading-none text-[13px] relative text-green9 select-none outline-none data-[highlighted]:ring-green9 data-[highlighted]:ring-1 focus:ring-green9 focus:ring-1 data-[state=checked]:bg-green9 data-[state=checked]:text-white data-[disabled]:opacity-50 rounded"
>
<ListboxItemIndicator
class="absolute left-0 w-[25px] inline-flex items-center justify-center"
>
<Icon icon="radix-icons:check" />
</ListboxItemIndicator>
<span>{{ i }}</span>
</ListboxItem>
</ListboxGroup>
<ListboxGroup class="mt-2">
<ListboxGroupLabel class="px-[25px] text-xs leading-[25px] text-mauve11">
Vegetables
</ListboxGroupLabel>
<ListboxItem
v-for="i in vegetables"
:key="i"
:value="i"
class="w-full flex items-center px-[25px] h-[25px] leading-none text-[13px] relative text-green9 select-none outline-none data-[highlighted]:ring-green9 data-[highlighted]:ring-1 focus:ring-green9 focus:ring-1 data-[state=checked]:bg-green9 data-[state=checked]:text-white data-[disabled]:opacity-50 rounded"
>
<ListboxItemIndicator
class="absolute left-0 w-[25px] inline-flex items-center justify-center"
>
<Icon icon="radix-icons:check" />
</ListboxItemIndicator>
<span>{{ i }}</span>
</ListboxItem>
</ListboxGroup>
</ListboxContent>
</ListboxRoot>
</template>
特性
- 可以是受控的或不受控的。
- 支持项目、标签、项目组。
- 焦点完全受管理。
- 完整的键盘导航。
- 支持从右到左方向。
- 不同的选择行为。
安装
从命令行安装组件。
$ npm add radix-vue
解剖结构
导入所有部分并将它们组合在一起。
<script setup>
import { ListboxContent, ListboxFilter, ListboxGroup, ListboxGroupLabel, ListboxItem, ListboxItemIndicator, ListboxRoot, ListboxVirtualizer } from 'radix-vue'
</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 | 布尔值 将默认渲染的元素更改为作为子元素传递的元素,合并其属性和行为。 阅读我们的 组合 指南了解更多详细信息。 | |
by | 字符串 | ((a: 可接受值, b: 可接受值) => 布尔值) 使用此方法根据特定字段比较对象,或传递您自己的比较函数以完全控制对象如何比较。 | |
defaultValue | 可接受值 | 可接受值[] 列表框在初始渲染时的值。当您不需要控制列表框的状态时使用 | |
dir | 'ltr' | 'rtl' 列表框的阅读方向(如果适用)。 | |
disabled | 布尔值 当 | |
highlightOnHover | 布尔值 当 | |
modelValue | 可接受值 | 可接受值[] 列表框的受控值。可以使用 | |
multiple | 布尔值 是否可以选择多个选项。 | |
name | 字符串 列表框的名称。作为名称/值对的一部分与其所属的表单一起提交。 | |
orientation | 'vertical' | 'vertical' | 'horizontal' 列表框的方向。 |
selectionBehavior | 'toggle' | 'replace' | 'toggle' 在集合中如何处理多选行为。 |
发射 | 有效载荷 |
---|---|
entryFocus | [事件: CustomEvent<any>] 容器被聚焦时调用的事件处理程序。可以阻止。 |
highlight | [有效载荷: { ref: HTMLElement; value: 可接受值; }] 突出显示元素发生变化时的事件处理程序。 |
leave | [事件: 事件] 鼠标离开容器时调用的事件处理程序 |
update:modelValue | [值: 可接受值] 值发生变化时调用的事件处理程序。 |
插槽 (默认) | 有效载荷 |
---|---|
modelValue | 可接受值 | 可接受值[] | 未定义 当前活动值 |
数据属性 | 值 |
---|---|
[data-disabled] | 禁用时存在 |
过滤器
用于执行过滤的输入元素。
属性 | 默认值 | 类型 |
---|---|---|
as | 'input' | AsTag | 组件 此组件应渲染成的元素或组件。可以被 |
asChild | 布尔值 将默认渲染的元素更改为作为子元素传递的元素,合并其属性和行为。 阅读我们的 组合 指南了解更多详细信息。 | |
autoFocus | 布尔值 安装时将焦点设置到元素上。 | |
modelValue | 字符串 过滤器的受控值。可以使用 v-model 进行绑定。 |
发射 | 有效载荷 |
---|---|
update:modelValue | [字符串] 值发生变化时调用的事件处理程序。 |
插槽 (默认) | 有效载荷 |
---|---|
modelValue | 字符串 | 未定义 当前输入值 |
数据属性 | 值 |
---|---|
[data-disabled] | 禁用时存在 |
内容
包含所有列表框组和项目。
属性 | 默认值 | 类型 |
---|---|---|
as | 'div' | AsTag | 组件 此组件应渲染成的元素或组件。可以被 |
asChild | 布尔值 将默认渲染的元素更改为作为子元素传递的元素,合并其属性和行为。 阅读我们的 组合 指南了解更多详细信息。 |
项目
项目组件。
属性 | 默认值 | 类型 |
---|---|---|
as | 'div' | AsTag | 组件 此组件应渲染成的元素或组件。可以被 |
asChild | 布尔值 将默认渲染的元素更改为作为子元素传递的元素,合并其属性和行为。 阅读我们的 组合 指南了解更多详细信息。 | |
disabled | 布尔值 当 | |
value* | 可接受值 使用 |
发射 | 有效载荷 |
---|---|
select | [事件: SelectEvent<可接受值>] 选择项目时调用的事件处理程序。 |
数据属性 | 值 |
---|---|
[data-state] | "checked" | "unchecked" |
[data-highlighted] | 突出显示时存在 |
[data-disabled] | 禁用时存在 |
项目指示器
当项目被选中时渲染。您可以直接设置此元素的样式,也可以将其用作包装器以放入图标,或者两者兼而有之。
属性 | 默认值 | 类型 |
---|---|---|
as | 'span' | AsTag | 组件 此组件应渲染成的元素或组件。可以被 |
asChild | 布尔值 将默认渲染的元素更改为作为子元素传递的元素,合并其属性和行为。 阅读我们的 组合 指南了解更多详细信息。 |
组
用于对多个项目进行分组。与 ListboxGroupLabel
结合使用,以确保通过自动标签提供良好的可访问性。
属性 | 默认值 | 类型 |
---|---|---|
as | 'div' | AsTag | 组件 此组件应渲染成的元素或组件。可以被 |
asChild | 布尔值 将默认渲染的元素更改为作为子元素传递的元素,合并其属性和行为。 阅读我们的 组合 指南了解更多详细信息。 |
组标签
用于渲染组的标签。它不能使用箭头键进行聚焦。
属性 | 默认值 | 类型 |
---|---|---|
as | 'div' | AsTag | 组件 此组件应渲染成的元素或组件。可以被 |
asChild | 布尔值 将默认渲染的元素更改为作为子元素传递的元素,合并其属性和行为。 阅读我们的 组合 指南了解更多详细信息。 | |
for | 字符串 |
虚拟化器
用于实现列表虚拟化的虚拟容器。
属性 | 默认值 | 类型 |
---|---|---|
estimateSize | 数字 每个项目的估计大小(以像素为单位) | |
options* | 可接受值[] 项目列表 | |
textContent | ((option: 可接受值) => 字符串) 每个项目的文本内容,用于实现提前输入功能 |
插槽 (默认) | 有效载荷 |
---|---|
option | 字符串 | 数字 | false | true | Record<字符串, 任何> |
示例
将对象绑定为值
与只能提供字符串作为值的原生 HTML 表单控件不同,radix-vue
还支持绑定复杂对象。
<script setup lang="ts">
import { ref } from 'vue'
import { ListboxContent, ListboxFilter, ListboxItem, ListboxRoot } from 'radix-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
组件允许您选择多个值。您可以通过提供一个值数组而不是单个值来启用此功能。
<script setup lang="ts">
import { ref } from 'vue'
import { ListboxRoot } from 'radix-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>
自定义过滤
<script setup lang="ts">
import { ref } from 'vue'
import { ListboxContent, ListboxFilter, ListboxItem, ListboxRoot } from 'radix-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 filteredPeople = computed(() =>
searchTerm.value === ''
? people
: people.filter((person) => {
return person.name.toLowerCase().includes(searchTerm.value.toLowerCase())
})
)
</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>
虚拟列表
渲染一个很长的项目列表会降低应用程序的速度,因此使用虚拟化会显着提高性能。
<script setup lang="ts">
import { ref } from 'vue'
import { ListboxContent, ListboxFilter, ListboxItem, ListboxRoot, ListboxVirtualizer } from 'radix-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>
<!-- checkout https://radix-vue.com/components/listbox.html#virtualizer -->
<ListboxVirtualizer
v-slot="{ option }"
:options="people"
:text-content="(opt) => opt.name"
>
<ListboxItem :value="option">
{{ person.name }}
</ListboxItem>
</ListboxVirtualizer>
</ListboxContent>
</ListboxRoot>
</template>
无障碍性
键盘交互
键 | 描述 |
---|---|
Enter | 当在 ListboxItem 上突出显示时,选择聚焦的项目。 |
ArrowDown | 当焦点在 ListboxItem 上时,将焦点移动到下一个项目。 |
ArrowUp | 当焦点在 ListboxItem 上时,将焦点移动到上一个项目。 |
Home | 将焦点和突出显示移动到第一个项目。 |
End | 将焦点和突出显示移动到最后一个项目。 |
Ctrl/Cmd + A | 选择所有项目。 |