Skip to content

Commit cfc2ef8

Browse files
Yan HengJessYan0913
authored andcommitted
feat: 新增Radio组件
1 parent ef75b67 commit cfc2ef8

File tree

5 files changed

+76
-38
lines changed

5 files changed

+76
-38
lines changed

main/src/components/Radio.vue

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<script setup lang="ts" generic="T">
2+
import { RadioCtxKey } from '@/constants/injection-keys';
3+
import { injectStrict } from '@/utils/vue';
4+
5+
defineProps<{
6+
value: T;
7+
}>();
8+
9+
const { modelValue } = injectStrict(RadioCtxKey);
10+
</script>
11+
12+
<template>
13+
<label class="radio">
14+
<input v-model="modelValue" type="radio" :value="value" />
15+
<div>
16+
<slot></slot>
17+
</div>
18+
</label>
19+
</template>
20+
21+
<style scoped lang="scss">
22+
.radio {
23+
border-radius: 0.5rem;
24+
display: inline-flex;
25+
align-items: center;
26+
position: relative;
27+
cursor: pointer;
28+
user-select: none;
29+
-webkit-tap-highlight-color: transparent;
30+
31+
& > input {
32+
position: absolute;
33+
opacity: 0;
34+
}
35+
36+
& > input:checked + div {
37+
background: #e3e2fe;
38+
}
39+
40+
div {
41+
width: 2.25rem;
42+
height: 2.25rem;
43+
display: flex;
44+
justify-content: center;
45+
align-items: center;
46+
border-radius: 0.5rem;
47+
}
48+
}
49+
</style>

main/src/components/RadioGroup.vue

Lines changed: 10 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<script setup lang="ts" generic="T">
2-
import { computed } from 'vue';
2+
import { computed, provide } from 'vue';
3+
4+
import { RadioCtxKey } from '@/constants/injection-keys';
35
46
export type RadioGroupOption<T> = {
57
value: T;
@@ -8,10 +10,10 @@ export type RadioGroupOption<T> = {
810
911
const props = defineProps<{
1012
modelValue: T;
11-
options: RadioGroupOption<T>[];
1213
}>();
1314
1415
const emits = defineEmits<{
16+
(event: 'change', value: T): void;
1517
(event: 'update:modelValue', value: T): void;
1618
}>();
1719
@@ -20,19 +22,19 @@ const selectedValue = computed<T>({
2022
return props.modelValue;
2123
},
2224
set(value: T) {
25+
emits('change', value);
2326
emits('update:modelValue', value);
2427
},
2528
});
29+
30+
provide(RadioCtxKey, {
31+
modelValue: selectedValue,
32+
});
2633
</script>
2734

2835
<template>
2936
<div class="radio-group">
30-
<label v-for="(item, index) in options" :key="index" class="radio">
31-
<input v-model="selectedValue" type="radio" :value="item.value" />
32-
<div>
33-
<slot :item="item"></slot>
34-
</div>
35-
</label>
37+
<slot></slot>
3638
</div>
3739
</template>
3840

@@ -44,35 +46,5 @@ const selectedValue = computed<T>({
4446
grid-auto-flow: column;
4547
gap: calc(0.25rem * 1);
4648
justify-items: center;
47-
48-
& > .radio {
49-
& > input {
50-
position: absolute;
51-
opacity: 0;
52-
}
53-
54-
& > input:checked + div {
55-
background: #e3e2fe;
56-
}
57-
}
58-
}
59-
60-
.radio {
61-
border-radius: 0.5rem;
62-
display: inline-flex;
63-
align-items: center;
64-
position: relative;
65-
cursor: pointer;
66-
user-select: none;
67-
-webkit-tap-highlight-color: transparent;
68-
69-
div {
70-
width: 2.25rem;
71-
height: 2.25rem;
72-
display: flex;
73-
justify-content: center;
74-
align-items: center;
75-
border-radius: 0.5rem;
76-
}
7749
}
7850
</style>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { InjectionKey } from 'vue';
2+
3+
import { RadioCtx } from '@/types';
4+
5+
export const RadioCtxKey: InjectionKey<RadioCtx<unknown>> = Symbol('RadioCtx');

main/src/types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export interface RadioCtx<T> {
2+
modelValue: T;
3+
}

main/src/utils/vue.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { inject, InjectionKey } from 'vue';
2+
3+
export const injectStrict = <T>(key: InjectionKey<T>, fallback?: T) => {
4+
const resolved = inject(key, fallback);
5+
if (!resolved) {
6+
throw new Error(`Could not resolve ${key.description}`);
7+
}
8+
return resolved;
9+
};

0 commit comments

Comments
 (0)