開關(切換)
開關是一種在兩個狀態之間切換值的友善介面,並提供與原生核取方塊元素相同的語意和鍵盤導覽功能。
首先,透過 npm 安裝 Headless 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>
Headless 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>
預設情況下,切換開關會呈現一個 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 核取方塊的標籤一樣。如果你想要讓這個標籤不可點擊(如果你覺得它不適合你的設計,你可能會這麼做),你可以將 passive
屬性新增至 SwitchLabel
元件
<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
道具,Headless 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 表單一併使用,或是要使用表格 API(這些 API 是利用 FormData 來收集其狀態,而不是使用 React 狀態來追蹤)時,此舉可以簡化你的程式碼。
你提供的任何 @update:modelValue
道具仍會在元件的值變更時被呼叫,萬一你需要執行任何副作用時,不過你不需要使用它來自己追蹤元件的狀態。
由於 Switch 通常總是會呈現在 DOM 中(與其他元件被掛載/解除掛載不同),因此簡單的 CSS 轉場動畫便足以用來為你的 Switch 加入動畫效果。
<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 的開或關。
指令 | 說明 |
Space 當 | 切換 Switch |
Enter 當在表單中時 | 提交表單 |
屬性 | 預設值 | 說明 |
as | button | 字串 | 元件
|
v-model | — | 布林值 切換開關是否為開啟狀態。 |
defaultChecked | — | T 使用非受控元件時的預設開啟值。 |
name | — | 字串 在此元件於表格中使用時使用的名稱。 |
value | — | 字串 在表格中使用此元件時,若元件已開啟,將會使用的值。 |
插槽屬性 | 說明 |
checked |
切換開關是否為開啟狀態。 |
屬性 | 預設值 | 說明 |
as | label | 字串 | 元件
|
passive | false | 布林值 為 true 時,點擊標籤不會切換 |
屬性 | 預設值 | 說明 |
as | p | 字串 | 元件
|
屬性 | 預設值 | 說明 |
as | template | 字串 | 元件
|