开关 (切换)

开关提供了一种友好的界面,用于在两种状态之间切换值,并提供与原生复选框元素相同的语义和键盘导航。

要开始使用,请通过 npm 安装无头 UI。

请注意,**此库仅支持 Vue 3**。

npm install @headlessui/vue

开关是使用 `Switch` 组件构建的,该组件通过 `v-model` 道具接收一个 ref。您可以通过直接点击组件或按下空格键(当它处于焦点状态时)来切换开关。

切换开关会将您的 ref 更新为其取反值。

<template> <Switch v-model="enabled" :class="enabled ? 'bg-blue-600' : 'bg-gray-200'" class="relative inline-flex h-6 w-11 items-center rounded-full" > <span class="sr-only">Enable notifications</span> <span :class="enabled ? 'translate-x-6' : 'translate-x-1'" class="inline-block h-4 w-4 transform rounded-full bg-white transition" /> </Switch> </template> <script setup> import { ref } from 'vue' import { Switch } from '@headlessui/vue' const enabled = ref(false) </script>

无头 UI 会跟踪每个组件的许多状态,例如当前选择了哪个开关选项,弹出窗口是打开还是关闭,或者菜单中哪个项目当前通过键盘处于活动状态。

但由于组件是无头且开箱即用完全没有样式的,因此您无法在 UI 中看到这些信息,直到您自己为每个状态提供所需的样式。

每个组件都通过插槽道具公开其当前状态的信息,您可以使用这些信息来有条件地应用不同的样式或渲染不同的内容。

例如,`Switch` 组件公开了一个 `checked` 状态,它告诉您开关当前是选中还是未选中。

<template>
<!-- Use the `checked` state to conditionally style the button. -->
<Switch v-model="enabled" as="template" v-slot="{ checked }"> <button class="relative inline-flex h-6 w-11 items-center rounded-full"
:class="checked ? 'bg-blue-600' : 'bg-gray-200'"
>
<span class="sr-only">Enable notifications</span> <span
:class="checked ? 'translate-x-6' : 'translate-x-1'"
class="inline-block h-4 w-4 transform rounded-full bg-white transition" />
</button> </Switch> </template> <script setup> import { ref } from 'vue' import { Switch } from '@headlessui/vue' const enabled = ref(false) </script>

有关所有可用插槽道具的完整列表,请参阅组件 API 文档

每个组件还通过 `data-headlessui-state` 属性公开其当前状态的信息,您可以使用它来有条件地应用不同的样式。

插槽道具 API 中的任何状态为 `true` 时,它们将在该属性中以空格分隔的字符串形式列出,以便您可以使用 CSS 属性选择器 以 `[attr~=value]` 的形式进行定位。

例如,以下是 `Switch` 组件在选中开关时渲染的内容

<!-- Rendered `Switch` --> <button data-headlessui-state="checked"></button>

如果您使用的是Tailwind CSS,您可以使用@headlessui/tailwindcss 插件以 `ui-checked:*` 等修饰符定位该属性

<template> <Switch v-model="enabled"
class="relative inline-flex h-6 w-11 items-center rounded-full ui-checked:bg-blue-600 ui-not-checked:bg-gray-200"
>
<span class="sr-only">Enable notifications</span> <span
class="inline-block h-4 w-4 transform rounded-full bg-white transition ui-checked:translate-x-6 ui-not-checked:translate-x-1"
/>
</Switch> </template> <script setup> import { ref } from 'vue' import { Switch } from '@headlessui/vue' const enabled = ref(false) </script>

默认情况下,Switch 会渲染一个 `button` 以及您传递给它的任何子元素。这可能会使某些 UI 的实现变得更加困难,因为子元素将嵌套在按钮内。

在这些情况下,您可以使用 `SwitchLabel` 组件来获得更大的灵活性。

此示例演示了如何使用 `SwitchGroup`、`Switch` 和 `SwitchLabel` 组件将标签渲染为按钮的同级元素。请注意,`SwitchLabel` 与 `Switch` 组件配合使用,它们都必须在父 `SwitchGroup` 组件内渲染。

<template>
<SwitchGroup>
<div class="flex items-center">
<SwitchLabel class="mr-4">Enable notifications</SwitchLabel>
<Switch v-model="enabled" :class='enabled ? "bg-blue-600" : "bg-gray-200"' class="relative inline-flex h-6 w-11 items-center rounded-full transition-colors focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2" > <span :class='enabled ? "translate-x-6" : "translate-x-1"' class="inline-block h-4 w-4 transform rounded-full bg-white transition-transform" /> </Switch> </div>
</SwitchGroup>
</template> <script setup> import { ref } from 'vue' import { Switch, SwitchGroup, SwitchLabel } from '@headlessui/vue' const enabled = ref(false) </script>

默认情况下,点击 `SwitchLabel` 会切换开关,就像原生 HTML 复选框中的标签一样。如果您想使标签不可点击(如果您认为它不适合您的设计,您可能会这样做),您可以在 `SwitchLabel` 组件中添加 `passive` 道具

<template> <SwitchGroup>
<SwitchLabel passive>Enable notifications</SwitchLabel>
<Switch v-model="enabled"> <!-- ... --> </Switch> </SwitchGroup> </template> <script setup> import { ref } from 'vue' import { Switch, SwitchGroup, SwitchLabel } from '@headlessui/vue' const enabled = ref(false) </script>

如果您在开关中添加 `name` 道具,则会渲染一个隐藏的 `input` 元素并与开关状态保持同步。

<template> <form action="/notification-settings" method="post">
<Switch v-model="enabled" name="notifications">
<!-- ... --> </Switch> </form> </template> <script setup> import { ref } from 'vue' import { Switch } from '@headlessui/vue' const enabled = ref(true) </script>

这使您可以在原生 HTML `<form>` 中使用开关,并进行传统的表单提交,就像您的开关是原生 HTML 表单控件一样。

默认情况下,当开关处于选中状态时,值为 `'on'`,而当开关处于未选中状态时,则不存在。

<input type="hidden" name="notifications" value="on" />

如果需要,您可以使用 `value` 道具自定义值

<template> <form action="/accounts" method="post">
<Switch v-model="enabled" name="terms" value="accept">
<!-- ... --> </Switch> </form> </template> <script setup> import { ref } from 'vue' import { Switch } from '@headlessui/vue' const enabled = ref(true) </script>

然后,隐藏的输入将在开关处于选中状态时使用您的自定义值

<input type="hidden" name="terms" value="accept" />

如果您向 `Switch` 提供 `defaultChecked` 道具而不是 `checked` 道具,无头 UI 将为您内部跟踪其状态,使您能够将其用作不受控组件

您可以通过 `Switch` 组件上的 `checked` 插槽道具访问当前状态。

<template> <form action="/accounts" method="post"> <Switch name="terms-of-service"
:defaultChecked="true"
as="template" v-slot="{ checked }" >
<button :class="checked ? 'bg-blue-600' : 'bg-gray-200'" class="relative inline-flex h-6 w-11 items-center rounded-full" > <span class="sr-only">Enable notifications</span> <span :class="checked ? 'translate-x-6' : 'translate-x-1'" class="inline-block h-4 w-4 transform rounded-full bg-white transition" /> </button> </Switch> <button>Submit</button> </form> </template> <script setup> import { Switch } from '@headlessui/vue' </script>

当与列表框一起使用 HTML 表单 或使用通过FormData 收集其状态而不是使用 React 状态跟踪其状态的表单 API 时,这可以简化您的代码。

您提供的任何 `@update:modelValue` 道具都将在组件的值更改时被调用,以防您需要运行任何副作用,但您不需要使用它来自己跟踪组件的状态。

由于开关通常始终渲染到 DOM(而不是像其他组件那样被挂载/卸载),因此简单的 CSS 过渡通常足以动画您的开关

<template> <Switch v-model="enabled"> <!-- Transition the switch's knob on state change --> <span
:class="enabled ? 'translate-x-9' : 'translate-x-0'"
class="transform transition duration-200 ease-in-out" />
<!-- ... --> </Switch> </template> <script setup> import { ref } from 'vue' import { Switch } from '@headlessui/vue' const enabled = ref(false) </script>

默认情况下,`Switch` 的子元素将用作屏幕阅读器的标签。如果您使用的是 `SwitchLabel`,您的 `Switch` 组件的内容将被辅助技术忽略。

点击 `Switch` 或 `SwitchLabel` 会切换开关的打开和关闭。

命令描述

空格 当 `Switch` 处于焦点状态时

切换开关

回车 当在表单中时

提交表单

所有相关的 ARIA 属性都会自动管理。

主要的 Switch 组件。

道具默认值描述
asbutton
字符串 | 组件

`Switch` 应渲染为的元素或组件。

v-model
布尔值

开关是否处于选中状态。

defaultChecked
T

使用作为不受控组件时的默认选中值。

name
字符串

在表单中使用此组件时使用的名称。

value
字符串

在表单中使用此组件时,如果它处于选中状态,则使用的值。

插槽道具描述
checked

布尔值

开关是否处于选中状态。

道具默认值描述
aslabel
字符串 | 组件

`SwitchLabel` 应渲染为的元素或组件。

passivefalse
布尔值

如果为 true,点击标签不会切换 `Switch`。

道具默认值描述
asp
字符串 | 组件

`Switch.Description` 应渲染为的元素或组件。

道具默认值描述
astemplate
字符串 | 组件

`SwitchGroup` 应渲染为的元素或组件。

如果您有兴趣使用无头 UI 和 Tailwind CSS 的预设计组件示例,请查看**Tailwind UI** - 由我们构建的一组精美设计和精心制作的组件。

这是一个支持我们对像这样的开源项目的工作的好方法,使我们能够改进它们并保持良好的维护。