radio
跟昨天的 checkbox
很相像,但使用情境結果大不同!
複習一下,checkbox
在面對單選時回傳的是 true
或 false
,一個以上的選項會變成複選的狀態。
但如果遇到一個必須回傳值的單選題(比如便當主餐只能選一個,不考慮雙主餐的情況)時,就會變得不好操作了~
這時候就能體現 radio 的優勢了,他能將選項的值回傳,且只可以選一個選項,後續也通常會搭配提交按鈕進行下一步。
一樣先思考 radio
有哪些狀態 🤔
disabled
禁止選取name
的欄位,賦予同一個值的話代表他們是同一題呦<input>
包在 <label>
裡面,如此就不需要使用 id 和 for 來進行連動
<script lang="ts" setup>
export interface RadioPropsType {
/** 標籤 */
label?: string
/** 預設是否勾選 */
checked?: boolean
/** 是否禁用 */
disabled?: boolean
/** name 標籤(group 使用) */
name?: string
/** input 選項代表的值 */
value?: any
/** 響應式值 */
modelValue?: any
}
const props = withDefaults(defineProps<RadioPropsType>(), {
label: '',
name: '',
value: '',
modelValue: ''
})
type EmitsEvent = (e: 'update:modelValue', value: any) => void
const emits = defineEmits<EmitsEvent>()
const ck = ref(props.checked)
const onChange = (): void => {
ck.value = !ck.value
}
const localValue = computed({
get: () => props.modelValue,
set: (newValue) => emits('update:modelValue', newValue)
})
</script>
<template>
<div>
<label
class="flex items-center"
:class="disabled ? ' cursor-not-allowed opacity-50' : 'cursor-pointer'"
>
<input
v-model="localValue"
type="radio"
class="hidden"
:disabled="disabled"
:name="name"
:value="value"
@change="onChange"
>
<span
:class="
localValue === value
? 'ring-primary-600 border-primary-600 ring-[6px] ring-inset ring-offset-2'
: 'border-slate-400'
"
class="relative inline-flex size-[18px] rounded-full border bg-white transition-all duration-150 mr-3"
/>
<span
v-if="label"
class="text-sm leading-6 text-slate-500"
>
{{ label }}
</span>
</label>
</div>
</template>
<script setup lang="ts">
const picked1 = ref('A')
const picked2 = ref('C')
const option = ref('ORANGE')
const options = [
{
value: 'ORANGE',
label: 'Orange'
},
{
value: 'APPLE',
label: 'Apple'
},
{
value: 'BANANA',
label: 'Banana'
}
]
</script>
<template>
<div class="relative">
<div class="flex flex-col text-xl gap-4 mb-4">
<h3>Radio 狀態</h3>
<div class="flex flex-wrap gap-4">
<Radio
v-model="picked1"
label="Checked"
class="mb-5"
name="x"
value="A"
/>
<Radio
v-model="picked1"
label="UnChecked"
:checked="true"
class="mb-5"
name="x"
value="B"
/>
<Radio
v-model="picked2"
label="Checked disabled"
disabled
class="mb-5"
name="x2"
value="C"
/>
<Radio
v-model="picked2"
label="UnChecked disabled"
name="x2"
disabled
class="mb-5"
value="D"
/>
</div>
</div>
<div class="flex flex-col text-xl gap-4 mb-4">
<h3>Radio 選取</h3>
<div
v-for="(item, i) in options"
:key="i"
>
<Radio
v-model="option"
:label="item.label"
class="mb-"
name="jorina"
:value="item.value"
/>
</div>
<div class="mt-3 text-slate-900 dark:text-slate-300">
Selected: {{ option }}
</div>
</div>
</div>
</template>