u
This commit is contained in:
1 parent
ae0ad2bd63
commit
5a7e96db02
12 files changed
+466
-85
No files matched your search
@@ -0,0 +1,112 @@
|
||||
import type { PropType, RenderFunction } from 'vue'
|
||||
import { computed, defineComponent, provide, reactive, ref, watch } from 'vue'
|
||||
import { getPrefixCls } from '../_utils/getPrefixCls'
|
||||
import Space from '../space/index'
|
||||
import { radioGroupKey } from './context'
|
||||
import Radio from './radio'
|
||||
|
||||
interface RadioOption {
|
||||
label?: string | RenderFunction
|
||||
value?: string | number
|
||||
extra?: string | RenderFunction
|
||||
disabled?: boolean
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'RadioGroup',
|
||||
props: {
|
||||
modelValue: {
|
||||
type: [String, Number, Boolean] as PropType<string | number | boolean>,
|
||||
default: undefined,
|
||||
},
|
||||
defaultValue: {
|
||||
type: [String, Number, Boolean] as PropType<string | number | boolean>,
|
||||
default: '',
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
labelField: {
|
||||
type: String,
|
||||
default: 'label',
|
||||
},
|
||||
valueField: {
|
||||
type: String,
|
||||
default: 'value',
|
||||
},
|
||||
options: {
|
||||
type: Array as PropType<Array<string | number | RadioOption>>,
|
||||
default: [],
|
||||
},
|
||||
spaceProps: {
|
||||
type: Object as PropType<Record<string, any>>,
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
emits: ['update:modelValue', 'change'],
|
||||
setup(props, { emit, slots }) {
|
||||
const prefixCls = getPrefixCls('radio-group')
|
||||
|
||||
// 内部值,优先使用 v-model
|
||||
const _value = ref(props.modelValue ?? props.defaultValue)
|
||||
|
||||
watch(() => props.modelValue, (newVal) => {
|
||||
if (newVal !== undefined) {
|
||||
_value.value = newVal
|
||||
}
|
||||
})
|
||||
|
||||
const handleChange = (val: string | number | boolean, e: Event) => {
|
||||
_value.value = val
|
||||
emit('update:modelValue', val)
|
||||
emit('change', val, e)
|
||||
}
|
||||
const groupDisabled = computed(() => props.disabled)
|
||||
|
||||
// 提供 context 给 Radio 使用
|
||||
provide(radioGroupKey, reactive({
|
||||
name: 'AoRadioGroup' as const,
|
||||
value: _value,
|
||||
disabled: groupDisabled,
|
||||
slots,
|
||||
handleChange,
|
||||
}))
|
||||
|
||||
const renderOptions = () => {
|
||||
return props.options.map((option) => {
|
||||
// 标准化 option
|
||||
const opt: RadioOption
|
||||
= typeof option === 'string' || typeof option === 'number'
|
||||
? { [props.labelField]: String(option), [props.valueField]: option }
|
||||
: option
|
||||
|
||||
const labelContent = slots.label
|
||||
? slots.label({ data: opt })
|
||||
: typeof opt[props.labelField] === 'function'
|
||||
? opt[props.labelField]()
|
||||
: opt[props.labelField]
|
||||
|
||||
return (
|
||||
<Radio
|
||||
key={opt[props.valueField]}
|
||||
value={opt[props.valueField]}
|
||||
disabled={opt.disabled ?? props.disabled}
|
||||
modelValue={_value.value === opt[props.valueField]}
|
||||
>
|
||||
{labelContent}
|
||||
</Radio>
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
return () => (
|
||||
<div class={[prefixCls]}>
|
||||
<Space {...props.spaceProps}>
|
||||
{props.options.length > 0 ? renderOptions() : slots.default?.()}
|
||||
</Space>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
})
|
||||
Reference in new issue
Block a user