开关 (切换)
开关提供了一种友好的界面,用于在两种状态之间切换值,并提供与原生复选框元素相同的语义和键盘导航。
要开始使用,请通过 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> <spanclass="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` 处于焦点状态时 | 切换开关 |
回车 当在表单中时 | 提交表单 |
道具 | 默认值 | 描述 |
as | button | 字符串 | 组件 `Switch` 应渲染为的元素或组件。 |
v-model | — | 布尔值 开关是否处于选中状态。 |
defaultChecked | — | T 使用作为不受控组件时的默认选中值。 |
name | — | 字符串 在表单中使用此组件时使用的名称。 |
value | — | 字符串 在表单中使用此组件时,如果它处于选中状态,则使用的值。 |
插槽道具 | 描述 |
checked |
开关是否处于选中状态。 |
道具 | 默认值 | 描述 |
as | label | 字符串 | 组件 `SwitchLabel` 应渲染为的元素或组件。 |
passive | false | 布尔值 如果为 true,点击标签不会切换 `Switch`。 |
道具 | 默认值 | 描述 |
as | p | 字符串 | 组件 `Switch.Description` 应渲染为的元素或组件。 |
道具 | 默认值 | 描述 |
as | template | 字符串 | 组件 `SwitchGroup` 应渲染为的元素或组件。 |