Skip to content
This repository was archived by the owner on Dec 6, 2021. It is now read-only.

Commit 4a453f4

Browse files
committed
feat(radio): add v-model support
1 parent d9fbce9 commit 4a453f4

File tree

4 files changed

+152
-130
lines changed

4 files changed

+152
-130
lines changed

src/components/radio/index.ts

+18-14
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,48 @@
1-
import { h, defineComponent, computed, mergeProps } from 'vue'
1+
import { h, defineComponent, computed, mergeProps, PropType } from 'vue'
22
import { Text, View } from '@tarojs/components'
33
import { CommonEvent } from '@tarojs/components/types/common'
44
import { AtRadioProps, RadioOption } from 'types/radio'
5+
import { useModelValue } from '../../composables/model'
56

67
const AtRadio = defineComponent({
78
name: "AtRadio",
89

910
props: {
1011
value: {
11-
type: String as () => AtRadioProps<any>['value'],
12+
type: String as PropType<AtRadioProps<any>['value']>,
1213
default: '',
1314
required: true
1415
},
1516
options: {
16-
type: Array as () => AtRadioProps<any>['options'],
17+
type: Array as PropType<AtRadioProps<any>['options']>,
1718
default: [],
1819
required: true
1920
},
20-
onClick: {
21-
type: Function as unknown as () => AtRadioProps<any>['onClick'],
22-
default: () => (vaule: any, event: CommonEvent) => { },
23-
required: true
24-
},
21+
onClick: Function as PropType<AtRadioProps<any>['onClick']>
2522
},
2623

27-
setup(props: AtRadioProps<any>, { attrs, slots }) {
24+
setup(props: AtRadioProps<any>, { attrs, emit }) {
2825

29-
const genOptionClass = computed(() => (option) => ({
26+
const radioModelValue = useModelValue(props, emit, 'value')
27+
28+
const genOptionClasses = computed(() => (option) => ({
3029
'at-radio__option': true,
3130
'at-radio__option--disabled': option.disabled
3231
}))
3332

34-
const genIconClass = computed(() => (option) => ({
33+
const genIconClasses = computed(() => (option) => ({
3534
'at-radio__icon': true,
3635
'at-radio__icon--checked': props.value === option.value
3736
}))
3837

3938
function handleClick(option: RadioOption<any>, event: CommonEvent): void {
4039
if (option.disabled) return
41-
props.onClick(option.value, event)
40+
41+
if (attrs['onUpdate:value']) {
42+
radioModelValue.value = option.value
43+
} else {
44+
props.onClick?.(option.value, event)
45+
}
4246
}
4347

4448
return () => (
@@ -48,7 +52,7 @@ const AtRadio = defineComponent({
4852
default: () => props.options.map(option => (
4953
h(View, {
5054
key: option.value,
51-
class: genOptionClass.value(option),
55+
class: genOptionClasses.value(option),
5256
onTap: handleClick.bind(this, option)
5357
}, {
5458
default: () => [
@@ -67,7 +71,7 @@ const AtRadio = defineComponent({
6771

6872
// icon
6973
h(View, {
70-
class: genIconClass.value(option)
74+
class: genIconClasses.value(option)
7175
}, {
7276
default: () => [
7377
h(Text, { class: 'at-icon at-icon-check' })

src/pages/form/radio/index.ts

-112
This file was deleted.

src/pages/form/radio/index.vue

+130
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
<template>
2+
<page header-title="Radio 单选框">
3+
<panel
4+
title="基础用法"
5+
no-padding
6+
>
7+
<view class="radio-container">
8+
<at-radio
9+
:options="radioOptions1"
10+
:value="radioValue1"
11+
@click="handleRadioChange"
12+
/>
13+
</view>
14+
</panel>
15+
16+
<panel
17+
title="含有单项描述"
18+
no-padding
19+
>
20+
<view class="radio-container">
21+
<at-radio
22+
:options="radioOptions2"
23+
:value="radioValue2"
24+
@click="handleRadioChange2nd"
25+
/>
26+
</view>
27+
</panel>
28+
29+
<panel
30+
title="使用 v-model: v-model:value"
31+
no-padding
32+
>
33+
<view class="radio-container">
34+
<at-radio
35+
:options="radioOptions2"
36+
v-model:value="radioValue2"
37+
/>
38+
</view>
39+
</panel>
40+
41+
<panel
42+
title="单项禁用"
43+
no-padding
44+
>
45+
<view class="radio-container">
46+
<at-radio
47+
:options="radioOptions3"
48+
:value="radioValue3"
49+
@click="handleRadioChange3rd"
50+
/>
51+
</view>
52+
</panel>
53+
</page>
54+
55+
</template>
56+
57+
<script lang="ts">
58+
import { defineComponent, reactive, toRefs } from 'vue'
59+
import { AtRadio } from '../../../index'
60+
import { RadioOption } from 'types/radio'
61+
import { Page, Panel } from '../../components/demo-page'
62+
import './index.scss'
63+
64+
interface IndexState {
65+
radioValue1: string
66+
radioValue2: string
67+
radioValue3: string
68+
radioOptions1: RadioOption<string>[]
69+
radioOptions2: RadioOption<string>[]
70+
radioOptions3: RadioOption<string>[]
71+
}
72+
73+
export default defineComponent({
74+
75+
name: "RadioDemo",
76+
77+
components: {
78+
AtRadio,
79+
Page,
80+
Panel
81+
},
82+
83+
setup() {
84+
85+
const state = reactive<IndexState>({
86+
radioValue1: 'option1',
87+
radioValue2: 'option1',
88+
radioValue3: 'option3',
89+
radioOptions1: [
90+
{ label: '单选项一', value: 'option1' },
91+
{ label: '单选项二', value: 'option2' },
92+
{ label: '单选项三', value: 'option3' }
93+
],
94+
radioOptions2: [
95+
{ label: '单选项一', value: 'option1', desc: '单选项描述一' },
96+
{ label: '单选项二', value: 'option2', desc: '单选项描述二' },
97+
{ label: '单选项三', value: 'option3', desc: '单选项描述三' }
98+
],
99+
radioOptions3: [
100+
{ label: '单选项一', value: 'option1', desc: '单选项描述' },
101+
{ label: '单选项二', value: 'option2' },
102+
{
103+
label: '单选项三禁用',
104+
value: 'option3',
105+
desc: '单选项描述',
106+
disabled: true
107+
}
108+
]
109+
})
110+
111+
function handleRadioChange(value: string): void {
112+
state.radioValue1 = value
113+
}
114+
function handleRadioChange2nd(value: string): void {
115+
state.radioValue2 = value
116+
}
117+
function handleRadioChange3rd(value: string): void {
118+
state.radioValue3 = value
119+
}
120+
121+
return {
122+
...toRefs(state),
123+
handleRadioChange,
124+
handleRadioChange2nd,
125+
handleRadioChange3rd
126+
}
127+
}
128+
})
129+
130+
</script>

types/radio.d.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
import { CommonEvent } from "@tarojs/components/types/common";
2+
import { CommonEvent } from "@tarojs/components/types/common"
33

44
import AtComponent from './base'
55

@@ -25,16 +25,16 @@ export interface RadioOption<T> {
2525

2626
export interface AtRadioProps<T> extends AtComponent {
2727
/**
28-
* 输入框当前值,用户需要通过 onClick 事件来更新 value 值,必填
28+
* 输入框当前值,支持 v-model,用户可通过 v-model:value 或 onClick 事件来更新 value 值,必填
2929
*/
3030
value: T
3131
/**
3232
* 选项列表
3333
*/
3434
options: Array<RadioOption<T>>
3535
/**
36-
* 点击选项触发事件,开发者需要通过此事件来更新 value,onClick 函数必填
36+
* 点击选项触发事件,开发者可通过此事件来更新 value
3737
*/
38-
onClick: (vaule: T, event: CommonEvent) => void
38+
onClick?: (vaule: T, event: CommonEvent) => void
3939
}
4040

0 commit comments

Comments
 (0)