选择
特性
- 可受控或非受控。
- 提供两种定位模式。
- 支持项、标签、项组。
- 焦点完全受控。
- 完整的键盘导航。
- 支持自定义占位符。
- 预输入支持。
- 支持从右到左方向。
安装
从命令行安装此组件。
$ npm add reka-ui
结构
导入所有部分并将其组合。
<script setup lang="ts">
import {
SelectContent,
SelectGroup,
SelectIcon,
SelectItem,
SelectItemIndicator,
SelectLabel,
SelectPortal,
SelectRoot,
SelectScrollDownButton,
SelectScrollUpButton,
SelectSeparator,
SelectTrigger,
SelectValue,
SelectViewport,
} from 'reka-ui'
</script>
<template>
<SelectRoot>
<SelectTrigger>
<SelectValue />
<SelectIcon />
</SelectTrigger>
<SelectPortal>
<SelectContent>
<SelectScrollUpButton />
<SelectViewport>
<SelectItem>
<SelectItemText />
<SelectItemIndicator />
</SelectItem>
<SelectGroup>
<SelectLabel />
<SelectItem>
<SelectItemText />
<SelectItemIndicator />
</SelectItem>
</SelectGroup>
<SelectSeparator />
</SelectViewport>
<SelectScrollDownButton />
<SelectArrow />
</SelectContent>
</SelectPortal>
</SelectRoot>
</template>
API 参考
根
包含 Select 的所有部分
属性 | 默认 | 类型 |
---|---|---|
autocomplete | string 原生 HTML input 的 `autocomplete` 属性。 | |
by | string | ((a: AcceptableValue, b: AcceptableValue) => boolean) 使用此项可通过特定字段比较对象,或传入您自己的比较函数以完全控制对象的比较方式。 | |
defaultOpen | 布尔值 Select 组件首次渲染时的打开状态。当您不需要控制其打开状态时使用。 | |
defaultValue | AcceptableValue | AcceptableValue[] Select 组件首次渲染时的值。当您不需要控制 Select 状态时使用。 | |
dir | 'ltr' | 'rtl' 适用时,组合框的阅读方向。 | |
disabled | 布尔值 当为 `true` 时,阻止用户与 Select 交互。 | |
modelValue | AcceptableValue | AcceptableValue[] Select 的受控值。可绑定为 `v-model`。 | |
multiple | 布尔值 是否可以选择多个选项。 | |
name | string 字段的名称。随其所属的表单一起作为名称/值对提交。 | |
open | 布尔值 Select 的受控打开状态。可绑定为 `v-model:open`。 | |
required | 布尔值 当为 |
事件触发 | 载荷 |
---|---|
update:modelValue | [value: AcceptableValue] 值改变时调用的事件处理程序。 |
update:open | [value: boolean] 当上下文菜单的打开状态改变时调用的事件处理程序。 |
插槽(默认) | 载荷 |
---|---|
modelValue | AcceptableValue | AcceptableValue[] | undefined 当前输入值 |
open | 布尔值 当前打开状态 |
触发器
切换 Select 的按钮。`SelectContent` 将通过与触发器对齐来定位自身。
属性 | 默认 | 类型 |
---|---|---|
as | 'button' | AsTag | Component 此组件应渲染为的元素或组件。可通过 |
asChild | 布尔值 更改默认渲染元素为作为子项传递的元素,合并它们的属性和行为。 阅读我们的 组合指南了解更多详情。 | |
disabled | 布尔值 | |
reference | ReferenceElement 用于定位的参考(或锚点)元素。 如果未提供,将使用当前组件作为锚点。 |
数据属性 | 值 |
---|---|
[data-state] | "打开" | "关闭" |
[data-disabled] | 禁用时存在 |
[data-placeholder] | 存在占位符时显示 |
值
反映选中值的部分。默认情况下,将渲染选中项的文本。如果您需要更多控制,可以改为控制 Select 并传入您自己的 `children`。它不应被样式化以确保正确的定位。当 Select 没有值时,还提供了一个可选的 `placeholder` 属性。
属性 | 默认 | 类型 |
---|---|---|
as | 'span' | AsTag | Component 此组件应渲染为的元素或组件。可通过 |
asChild | 布尔值 更改默认渲染元素为作为子项传递的元素,合并它们的属性和行为。 阅读我们的 组合指南了解更多详情。 | |
placeholder | '' | string 当未设置 `value` 或 `defaultValue` 时,将在 `SelectValue` 内部渲染的内容。 |
插槽(默认) | 载荷 |
---|---|
selectedLabel | string[] |
modelValue | AcceptableValue | AcceptableValue[] | undefined |
图标
一个小图标,通常显示在值旁边,作为可打开的视觉提示。默认渲染 ▼,但您可以通过 `asChild` 或使用 `children` 来使用您自己的图标。
属性 | 默认 | 类型 |
---|---|---|
as | 'div' | AsTag | Component 此组件应渲染为的元素或组件。可通过 |
asChild | 布尔值 更改默认渲染元素为作为子项传递的元素,合并它们的属性和行为。 阅读我们的 组合指南了解更多详情。 | |
disabled | 布尔值 当为 | |
textValue | string 用于预输入目的的可选文本。 默认情况下,预输入行为将使用 `SelectItemText` 部分的 `.textContent`。 当内容复杂或包含非文本内容时使用此项。 | |
值* | AcceptableValue 与 `name` 一起提交时作为数据给出的值。 |
事件触发 | 载荷 |
---|---|
select | [event: SelectEvent<AcceptableValue>] 选择项时调用的事件处理程序。 |
传送门
使用时,将内容部分传送到 body
中。
属性 | 默认 | 类型 |
---|---|---|
defer | 布尔值 延迟解析 Teleport 目标,直到应用程序的其他部分挂载(需要 Vue 3.5.0+) | |
disabled | 布尔值 禁用传送并内联渲染组件 | |
forceMount | 布尔值 当需要更多控制时,用于强制挂载。在与 Vue 动画库控制动画时很有用。 | |
to | 字符串 | HTMLElement Vue 原生传送组件属性 |
内容
当 Select 打开时弹出的组件。
属性 | 默认 | 类型 |
---|---|---|
align | 'start' | 'center' | 'end' 相对于触发器的首选对齐方式。当发生碰撞时可能会改变。 | |
alignOffset | 数字 与 | |
arrowPadding | 数字 箭头与内容边缘之间的内边距。如果您的内容有 border-radius,这将防止它溢出角落。 | |
as | 'div' | AsTag | Component 此组件应渲染为的元素或组件。可通过 |
asChild | 布尔值 更改默认渲染元素为作为子项传递的元素,合并它们的属性和行为。 阅读我们的 组合指南了解更多详情。 | |
avoidCollisions | 布尔值 当为 | |
bodyLock | 布尔值 文档主体将被锁定,滚动将被禁用。 | |
collisionBoundary | Element | (Element | null)[] | null 用作碰撞边界的元素。默认情况下是视口,但您可以提供其他元素以包含在此检查中。 | |
collisionPadding | 数字 | Partial<Record<'top' | 'right' | 'bottom' | 'left', number>> 碰撞检测应发生的距边界边缘的像素距离。接受一个数字(所有边相同),或一个部分填充对象,例如:{ top: 20, left: 20 }。 | |
disableUpdateOnLayoutShift | 布尔值 当布局发生偏移时,是否禁用更新内容位置。 | |
forceMount | 布尔值 当需要更多控制时,用于强制挂载。在与 Vue 动画库控制动画时很有用。 | |
hideWhenDetached | 布尔值 当触发器完全被遮挡时,是否隐藏内容。 | |
position | 'popper' | 'item-aligned' 要使用的定位模式 `item-aligned (默认)` - 通过将内容相对于活动项定位,其行为类似于原生 macOS 菜单。 | |
positionStrategy | 'fixed' | 'absolute' 要使用的 CSS position 属性类型。 | |
prioritizePosition | 布尔值 强制内容在视口内定位。 可能与参考元素重叠,这可能不是期望的结果。 | |
reference | ReferenceElement 将设置为浮动元素定位参考的自定义元素或虚拟元素。 如果提供,它将替换默认的锚点元素。 | |
side | 'top' | 'right' | 'bottom' | 'left' 打开时,相对于触发器渲染的首选侧边。当发生碰撞且启用 avoidCollisions 时,将反转。 | |
sideOffset | 数字 与触发器的像素距离。 | |
sticky | '部分' | '始终' 对齐轴上的粘性行为。 | |
updatePositionStrategy | '始终' | '优化' 在每个动画帧更新浮动元素位置的策略。 |
事件触发 | 载荷 |
---|---|
closeAutoFocus | [事件: Event] 关闭时自动聚焦调用的事件处理程序。可阻止其默认行为。 |
escapeKeyDown | [事件: KeyboardEvent] 按下 Esc 键时调用的事件处理程序。可阻止其默认行为。 |
pointerDownOutside | [事件: PointerDownOutsideEvent] 当 |
数据属性 | 值 |
---|---|
[data-state] | "打开" | "关闭" |
[data-side] | "左" | "右" | "下" | "上" |
[data-align] | "开始" | "结束" | "居中" |
CSS 变量 | 描述 |
---|---|
--reka-select-content-transform-origin | 根据内容和箭头位置/偏移量计算的 `transform-origin`。仅当 `position="popper"` 时存在。 |
--reka-select-content-available-width | 触发器与边界边缘之间的剩余宽度。仅当 `position="popper"` 时存在。 |
--reka-select-content-available-height | 触发器与边界边缘之间的剩余高度。仅当 `position="popper"` 时存在。 |
--reka-select-trigger-width | 触发器的宽度。仅当 `position="popper"` 时存在。 |
--reka-select-trigger-height | 触发器的高度。仅当 `position="popper"` 时存在。 |
视口
包含所有项的可滚动视口。
属性 | 默认 | 类型 |
---|---|---|
as | 'div' | AsTag | Component 此组件应渲染为的元素或组件。可通过 |
asChild | 布尔值 更改默认渲染元素为作为子项传递的元素,合并它们的属性和行为。 阅读我们的 组合指南了解更多详情。 | |
nonce | string 将向 style 标签添加 `nonce` 属性,此属性可用于内容安全策略(Content Security Policy)。 |
项
包含选择项的组件。
属性 | 默认 | 类型 |
---|---|---|
as | 'div' | AsTag | Component 此组件应渲染为的元素或组件。可通过 |
asChild | 布尔值 更改默认渲染元素为作为子项传递的元素,合并它们的属性和行为。 阅读我们的 组合指南了解更多详情。 | |
disabled | 布尔值 当为 | |
textValue | string 用于预输入目的的可选文本。 默认情况下,预输入行为将使用 `SelectItemText` 部分的 `.textContent`。 当内容复杂或包含非文本内容时使用此项。 | |
值* | AcceptableValue 与 `name` 一起提交时作为数据给出的值。 |
事件触发 | 载荷 |
---|---|
select | [event: SelectEvent<AcceptableValue>] 选择项时调用的事件处理程序。 |
数据属性 | 值 |
---|---|
[data-state] | "选中" | "未选中" |
[data-highlighted] | 高亮时存在 |
[data-disabled] | 禁用时存在 |
项文本
项的文本部分。它应只包含您希望在该项被选中时在触发器中看到的文本。不应为其设置样式以确保正确的定位。
属性 | 默认 | 类型 |
---|---|---|
as | 'span' | AsTag | Component 此组件应渲染为的元素或组件。可通过 |
asChild | 布尔值 更改默认渲染元素为作为子项传递的元素,合并它们的属性和行为。 阅读我们的 组合指南了解更多详情。 |
项指示器
当项目被选中时渲染。您可以直接设置此元素的样式,或者将其用作包装器以放入图标,或两者兼而有之。
属性 | 默认 | 类型 |
---|---|---|
as | 'span' | AsTag | Component 此组件应渲染为的元素或组件。可通过 |
asChild | 布尔值 更改默认渲染元素为作为子项传递的元素,合并它们的属性和行为。 阅读我们的 组合指南了解更多详情。 |
向上滚动按钮
一个可选按钮,用作显示视口溢出的提示,并可在功能上启用向上滚动。
属性 | 默认 | 类型 |
---|---|---|
as | 'div' | AsTag | Component 此组件应渲染为的元素或组件。可通过 |
asChild | 布尔值 更改默认渲染元素为作为子项传递的元素,合并它们的属性和行为。 阅读我们的 组合指南了解更多详情。 |
向下滚动按钮
一个可选按钮,用作显示视口溢出的提示,并可在功能上启用向下滚动。
属性 | 默认 | 类型 |
---|---|---|
as | 'div' | AsTag | Component 此组件应渲染为的元素或组件。可通过 |
asChild | 布尔值 更改默认渲染元素为作为子项传递的元素,合并它们的属性和行为。 阅读我们的 组合指南了解更多详情。 |
分组
用于将多个项分组。与 `SelectLabel` 结合使用,通过自动标记确保良好的可访问性。
属性 | 默认 | 类型 |
---|---|---|
as | 'div' | AsTag | Component 此组件应渲染为的元素或组件。可通过 |
asChild | 布尔值 更改默认渲染元素为作为子项传递的元素,合并它们的属性和行为。 阅读我们的 组合指南了解更多详情。 |
标签
用于渲染组的标签。它无法通过箭头键聚焦。
属性 | 默认 | 类型 |
---|---|---|
as | 'div' | AsTag | Component 此组件应渲染为的元素或组件。可通过 |
asChild | 布尔值 更改默认渲染元素为作为子项传递的元素,合并它们的属性和行为。 阅读我们的 组合指南了解更多详情。 | |
for | string |
分隔符
用于在 Select 中视觉上分隔各项。
属性 | 默认 | 类型 |
---|---|---|
as | 'div' | AsTag | Component 此组件应渲染为的元素或组件。可通过 |
asChild | 布尔值 更改默认渲染元素为作为子项传递的元素,合并它们的属性和行为。 阅读我们的 组合指南了解更多详情。 |
箭头
一个可选的箭头元素,与内容一起渲染。这可用于帮助在视觉上将触发器与 `SelectContent` 关联起来。必须在 `SelectContent` 内部渲染。仅当 `position` 设置为 `popper` 时可用。
属性 | 默认 | 类型 |
---|---|---|
as | 'svg' | AsTag | Component 此组件应渲染为的元素或组件。可通过 |
asChild | 布尔值 更改默认渲染元素为作为子项传递的元素,合并它们的属性和行为。 阅读我们的 组合指南了解更多详情。 | |
高度 | 5 | 数字 箭头的像素高度。 |
rounded | 布尔值 当为 | |
宽度 | 10 | 数字 箭头的像素宽度。 |
示例
改变定位模式
默认情况下,`Select` 的行为类似于原生 macOS 菜单,它将 `SelectContent` 相对于活动项进行定位。如果您更喜欢类似于 `Popover` 或 `DropdownMenu` 的替代定位方法,则可以将 `position` 设置为 `popper` 并使用额外的对齐选项,例如 `side`、`sideOffset` 等。
// index.vue
<script setup lang="ts">
import {
SelectContent,
SelectGroup,
SelectItem,
SelectItemIndicator,
SelectLabel,
SelectPortal,
SelectRoot,
SelectSeparator,
SelectTrigger,
} from 'reka-ui'
</script>
<template>
<SelectRoot>
<SelectTrigger>…</SelectTrigger>
<SelectPortal>
<SelectContent
position="popper"
:side-offset="5"
>
…
</SelectContent>
</SelectPortal>
</SelectRoot>
</template>
约束内容大小
在 `SelectContent` 上使用 `position="popper"` 时,您可能希望约束内容的宽度以使其与触发器宽度匹配。您还可能希望约束其高度,使其不超过视口。
我们公开了几个 CSS 自定义属性,例如 `--reka-select-trigger-width` 和 `--reka-select-content-available-height` 来支持此功能。使用它们来约束内容的尺寸。
// index.vue
<script setup lang="ts">
import {
SelectContent,
SelectGroup,
SelectItem,
SelectItemIndicator,
SelectLabel,
SelectPortal,
SelectRoot,
SelectSeparator,
SelectTrigger,
} from 'reka-ui'
</script>
<template>
<SelectRoot>
<SelectTrigger>…</SelectTrigger>
<SelectPortal>
<SelectContent
class="SelectContent"
position="popper"
:side-offset="5"
>
…
</SelectContent>
</SelectPortal>
</SelectRoot>
</template>
/* styles.css */
.SelectContent {
width: var(--reka-select-trigger-width);
max-height: var(--reka-select-content-available-height);
}
带有禁用项
您可以通过 data-disabled
属性为禁用项目添加特殊样式。
// index.vue
<script setup lang="ts">
import {
SelectContent,
SelectGroup,
SelectItem,
SelectItemIndicator,
SelectLabel,
SelectPortal,
SelectRoot,
SelectSeparator,
SelectTrigger,
} from 'reka-ui'
</script>
<template>
<SelectRoot>
<SelectTrigger>…</SelectTrigger>
<SelectPortal>
<SelectContent>
<SelectViewport>
<SelectItem
class="SelectItem"
disabled
>
…
</SelectItem>
<SelectItem>…</SelectItem>
<SelectItem>…</SelectItem>
</SelectViewport>
</SelectContent>
</SelectPortal>
</SelectRoot>
</template>
/* styles.css */
.SelectItem[data-disabled] {
color: "gainsboro";
}
带有占位符
当 Select 没有值时,您可以在 `Value` 上使用 `placeholder` 属性。`Trigger` 上还有一个 `data-placeholder` 属性,用于帮助样式设计。
// index.vue
<script setup lang="ts">
import {
SelectContent,
SelectGroup,
SelectItem,
SelectItemIndicator,
SelectLabel,
SelectPortal,
SelectRoot,
SelectSeparator,
SelectTrigger,
} from 'reka-ui'
import './styles.css'
</script>
<template>
<SelectRoot>
<SelectTrigger class="SelectTrigger">
<SelectValue placeholder="Pick an option" />
<SelectIcon />
</SelectTrigger>
<SelectPortal>
<SelectContent>…</SelectContent>
</SelectPortal>
</SelectRoot>
</template>
/* styles.css */
.SelectTrigger[data-placeholder] {
color: "gainsboro";
}
带有分隔符
使用 Separator
部分在项目之间添加分隔符。
<template>
<SelectRoot>
<SelectTrigger>…</SelectTrigger>
<SelectPortal>
<SelectContent>
<SelectViewport>
<SelectItem>…</SelectItem>
<SelectItem>…</SelectItem>
<SelectItem>…</SelectItem>
<SelectSeparator />
<SelectItem>…</SelectItem>
<SelectItem>…</SelectItem>
</SelectViewport>
</SelectContent>
</SelectPortal>
</SelectRoot>
</template>
带有分组项
使用 `Group` 和 `Label` 部分将项分组。
<template>
<SelectRoot>
<SelectTrigger>…</SelectTrigger>
<SelectPortal>
<SelectContent>
<SelectViewport>
<SelectGroup>
<SelectLabel>Label</SelectLabel>
<SelectItem>…</SelectItem>
<SelectItem>…</SelectItem>
<SelectItem>…</SelectItem>
</SelectGroup>
</SelectViewport>
</SelectContent>
</SelectPortal>
</SelectRoot>
</template>
带有复杂项
您可以在您的项中使用自定义内容。
<script setup lang="ts">
import {
SelectContent,
SelectGroup,
SelectItem,
SelectItemIndicator,
SelectLabel,
SelectPortal,
SelectRoot,
SelectSeparator,
SelectTrigger,
} from 'reka-ui'
</script>
<template>
<SelectRoot>
<SelectTrigger>…</SelectTrigger>
<SelectPortal>
<SelectContent>
<SelectViewport>
<SelectItem>
<SelectItemText>
<img src="…">
Adolfo Hess
</SelectItemText>
<SelectItemIndicator>…</SelectItemIndicator>
</SelectItem>
<SelectItem>…</SelectItem> <SelectItem>…</SelectItem>
</SelectViewport>
</SelectContent>
</SelectPortal>
</SelectRoot>
</template>
控制触发器中显示的值
默认情况下,触发器显示选中项的文本(不再像 v1 中那样自动渲染 `ItemText` 的内容)。
如果您需要渲染非纯文本内容,可以通过 `v-model` 属性(或访问 `SelectValue` 的 slotProps)来控制组件,并向 `SelectValue` 传递 `slot`。请记住确保您放入的内容是可访问的。
<script setup>
const countries = { 'france': '🇫🇷', 'united-kingdom': '🇬🇧', 'spain': '🇪🇸' }
const value = ref('france')
</script>
<template>
<SelectRoot v-model="value">
<SelectTrigger>
<SelectValue :aria-label="value">
{{ countries[value] }}
</SelectValue>
<SelectIcon />
</SelectTrigger>
<SelectPortal>
<SelectContent>
<SelectViewport>
<SelectItem value="france">
<SelectItemText>France</SelectItemText>
<SelectItemIndicator>…</SelectItemIndicator>
</SelectItem>
<SelectItem value="united-kingdom">
<SelectItemText>United Kingdom</SelectItemText>
<SelectItemIndicator>…</SelectItemIndicator>
</SelectItem>
<SelectItem value="spain">
<SelectItemText>Spain</SelectItemText>
<SelectItemIndicator>…</SelectItemIndicator>
</SelectItem>
</SelectViewport>
</SelectContent>
</SelectPortal>
</SelectRoot>
</template>
带有自定义滚动条
默认情况下,原生滚动条是隐藏的,因为我们建议使用 `ScrollUpButton` 和 `ScrollDownButton` 部分以获得最佳用户体验。如果您不想使用这些部分,可以使用我们的 滚动区域 原语来组合您的 Select 组件。
// index.vue
<script setup lang="ts">
import {
ScrollAreaRoot,
ScrollAreaScrollbar,
ScrollAreaThumb,
ScrollAreaViewport,
SelectContent,
SelectGroup,
SelectItem,
SelectItemIndicator,
SelectLabel,
SelectPortal,
SelectRoot,
SelectSeparator,
SelectTrigger,
} from 'reka-ui'
</script>
<template>
<SelectRoot>
<SelectTrigger>…</SelectTrigger>
<SelectPortal>
<SelectContent>
<ScrollAreaRoot
class="ScrollAreaRoot"
type="auto"
>
<SelectViewport as-child>
<ScrollAreaViewport class="ScrollAreaViewport">
<StyledItem>…</StyledItem> <StyledItem>…</StyledItem>
<StyledItem>…</StyledItem>
</ScrollAreaViewport>
</SelectViewport>
<ScrollAreaScrollbar
class="ScrollAreaScrollbar"
orientation="vertical"
>
<ScrollAreaThumb class="ScrollAreaThumb" />
</ScrollAreaScrollbar>
</ScrollAreaRoot>
</SelectContent>
</SelectPortal>
</SelectRoot>
</template>
/* styles.css */
.ScrollAreaRoot {
width: 100%;
height: 100%;
}
.ScrollAreaViewport {
width: 100%;
height: 100%;
}
.ScrollAreaScrollbar {
width: 4px;
padding: 5px 2px;
}
.ScrollAreaThumb {
background: rgba(0, 0, 0, 0.3);
borderradius: 3px;
}
可访问性
有关更多信息,请参阅 W3C 仅选择组合框 示例。
键盘交互
键 | 描述 |
---|---|
空格键 | 当焦点在 `SelectTrigger` 上时,打开 Select 并聚焦于选中项。 当焦点在某个项上时,选择该聚焦项。 |
回车键 | 当焦点在 `SelectTrigger` 上时,打开 Select 并聚焦于第一个项。 当焦点在某个项上时,选择该聚焦项。 |
向下箭头键 | 当焦点在 `SelectTrigger` 上时,打开 Select。 当焦点在项目上时,将焦点移到下一个项目。 |
向上箭头键 | 当焦点在 `SelectTrigger` 上时,打开 Select。 当焦点在项目上时,将焦点移到上一个项目。 |
Esc键 | 关闭 Select 并将焦点移至 `SelectTrigger`。 |
标记
使用我们的 Label 组件为 Select 提供可视化和可访问的标签。
<script setup lang="ts">
import { Icon } from '@iconify/vue'
import {
Label,
SelectContent,
SelectGroup,
SelectItem,
SelectItemIndicator,
SelectLabel,
SelectPortal,
SelectRoot,
SelectSeparator,
SelectTrigger,
} from 'reka-ui'
import { ref } from 'vue'
</script>
<template>
<Label>
Country
<SelectRoot>…</SelectRoot>
</Label>
<!-- or -->
<Label for="country">Country</Label>
<SelectRoot>
<SelectTrigger id="country">
…
</SelectTrigger>
<SelectPortal>
<SelectContent>…</SelectContent>
</SelectPortal>
</SelectRoot>
</template>
自定义 API
通过将原始部件抽象到您自己的组件中来创建您自己的 API。
抽象为 `Select` 和 `SelectItem`
此示例抽象了大部分组件。
用法
<script setup lang="ts">
import { Select, SelectItem } from './your-select'
</script>
<template>
<Select default-value="2">
<SelectItem value="1">
Item 1
</SelectItem>
<SelectItem value="2">
Item 2
</SelectItem>
<SelectItem value="3">
Item 3
</SelectItem>
</Select>
</template>
实现
// your-select.ts
export { default as Select } from 'Select.vue'
export { default as SelectItem } from 'SelectItem.vue'
<!-- Select.vue -->
<script setup lang="ts">
import type { SelectRootEmits, SelectRootProps } from 'reka-ui'
import { CheckIcon, ChevronDownIcon, ChevronUpIcon, } from '@radix-icons/vue'
import { SelectContent, SelectIcon, SelectPortal, SelectRoot, SelectScrollDownButton, SelectScrollUpButton, SelectTrigger, SelectValue, SelectViewport, useForwardPropsEmits } from 'reka-ui'
const props = defineProps<SelectRootProps>()
const emits = defineEmits<SelectRootEmits>()
const forward = useForwardPropsEmits(props, emits)
</script>
<template>
<SelectRoot v-bind="forward">
<SelectTrigger>
<SelectValue />
<SelectIcon>
<ChevronDownIcon />
</SelectIcon>
</SelectTrigger>
<SelectPortal>
<SelectContent>
<SelectScrollUpButton>
<ChevronUpIcon />
</SelectScrollUpButton>
<SelectViewport>
<slot />
</SelectViewport>
<SelectScrollDownButton>
<ChevronDownIcon />
</SelectScrollDownButton>
</SelectContent>
</SelectPortal>
</SelectRoot>
</template>
<!-- SelectItem.vue -->
<script setup lang="ts">
import type { SelectItemProps } from 'reka-ui'
import { CheckIcon } from '@radix-icons/vue'
import { SelectItem, SelectItemIndicator, SelectItemText } from 'reka-ui'
const props = defineProps<SelectItemProps>()
</script>
<template>
<SelectItem v-bind="props">
<SelectItemText>
<slot />
</SelectItemText>
<SelectItemIndicator>
<CheckIcon />
</SelectItemIndicator>
</SelectItem>
</template>