volunteer-4/src/login-sub/components/radio-group/Radio.vue

90 lines
1.7 KiB
Vue

<template>
<label
class="radio-wrapper"
:class="{ 'radio-wrapper--disabled': isDisabled }"
@click.stop="handleClick"
>
<radio
class="radio"
:value="String(name)"
:checked="isChecked"
:disabled="isDisabled"
:color="isChecked ? '#0083ff' : ''"
:name="String(name)"
/>
<view class="radio-label" :class="{ 'radio-label--active': isChecked }">
<slot>{{ label }}</slot>
</view>
</label>
</template>
<script lang="ts" setup>
import { computed, inject } from 'vue'
const props = defineProps({
name: {
type: [String, Number],
required: true,
},
label: {
type: String,
default: '',
},
disabled: {
type: Boolean,
default: false,
},
})
interface RadioGroupContext {
modelValue: ComputedRef<string | number>
disabled: ComputedRef<boolean>
toggleOption: (value: string | number) => void
}
// 注入radio group的上下文
const radioGroup = inject<RadioGroupContext>('radioGroup', {
modelValue: computed(() => ''),
disabled: computed(() => false),
toggleOption: () => {},
})
// 是否选中
const isChecked = computed(() => {
return radioGroup.modelValue.value === props.name
})
// 是否禁用
const isDisabled = computed(() => {
return props.disabled || radioGroup.disabled.value
})
// 处理点击事件
const handleClick = () => {
if (isDisabled.value) return
radioGroup.toggleOption(props.name)
}
</script>
<style scoped lang="scss">
.radio-wrapper {
display: inline-flex;
align-items: center;
font-size: 28rpx;
padding: 8rpx 0;
&--disabled {
opacity: 0.5;
}
}
.radio-label {
margin-left: 10rpx;
line-height: 1;
&--active {
color: #0083ff;
}
}
</style>