提交 424f7e2e 编写于 作者: d-u-a's avatar d-u-a

fix(nvue3): radio-group

上级 84017bc5
import { WritableComputedRef, ExtractPropTypes } from 'vue'
import { PolySymbol } from '@dcloudio/uni-core'
export const uniRadioGroupKey = PolySymbol(__DEV__ ? 'uniRadioGroup' : 'ucg')
export type UniRadioGroupFieldCtx = WritableComputedRef<{
radioChecked: boolean
value: string
}>
export interface UniRadioGroupCtx {
addField: (field: UniRadioGroupFieldCtx) => void
removeField: (field: UniRadioGroupFieldCtx) => void
radioChange: ($event: Event, field: UniRadioGroupFieldCtx) => void
}
export const radioGroupProps = {
name: {
type: String,
default: '',
},
}
export type RadioGroupProps = ExtractPropTypes<typeof radioGroupProps>
......@@ -2,41 +2,27 @@ import {
defineComponent,
inject,
provide,
ComputedRef,
ref,
ExtractPropTypes,
onBeforeUnmount,
onMounted,
} from 'vue'
import { uniRadioGroupKey } from '../../components/radio-group'
import {
uniRadioGroupKey,
UniRadioGroupFieldCtx,
UniRadioGroupCtx,
RadioGroupProps,
radioGroupProps,
} from '../../components/radio-group'
import { UniFormCtx, uniFormKey } from '../../components/form'
import {
CustomEventTrigger,
useCustomEvent,
EmitEvent,
} from '../../helpers/useEvent'
type UniRadioGroupFieldCtx = ComputedRef<{
radioChecked: boolean
value: string
}>
const props = {
name: {
type: String,
default: '',
},
}
type RadioGroupProps = ExtractPropTypes<typeof props>
export interface UniRadioGroupCtx {
addField: (field: UniRadioGroupFieldCtx) => void
removeField: (field: UniRadioGroupFieldCtx) => void
radioChange: ($event: Event) => void
}
} from '../../helpers/useNVueEvent'
export default defineComponent({
name: 'RadioGroup',
props,
props: radioGroupProps,
emits: ['change'],
setup(props, { slots, emit }) {
const rootRef = ref<HTMLElement | null>(null)
......@@ -56,13 +42,12 @@ function useProvideRadioGroup(
) {
const fields: UniRadioGroupFieldCtx[] = []
onMounted(() => {
_resetRadioGroupValue(fields.length - 1)
})
const getFieldsValue = () =>
fields.reduce((res, field) => {
if (field.value.radioChecked) {
res.push(field.value.value)
}
return res
}, new Array())
fields.find((field) => field.value.radioChecked)?.value.value
provide<UniRadioGroupCtx>(uniRadioGroupKey, {
addField(field: UniRadioGroupFieldCtx) {
......@@ -71,26 +56,53 @@ function useProvideRadioGroup(
removeField(field: UniRadioGroupFieldCtx) {
fields.splice(fields.indexOf(field), 1)
},
radioChange($event) {
trigger('change', $event, {
radioChange($event: Event, field: UniRadioGroupFieldCtx) {
const index = fields.indexOf(field)
_resetRadioGroupValue(index, true)
trigger('change', {
value: getFieldsValue(),
})
},
})
const uniForm = inject<UniFormCtx>(uniFormKey, false as unknown as UniFormCtx)
const formField = {
submit: () => {
let data: [string, any] = ['', null]
if (props.name !== '') {
data[0] = props.name
data[1] = getFieldsValue()
}
return data
},
}
if (uniForm) {
uniForm.addField({
submit: () => {
let data: [string, any] = ['', null]
if (props.name !== '') {
data[0] = props.name
data[1] = getFieldsValue()
}
return data
},
uniForm.addField(formField)
onBeforeUnmount(() => {
uniForm.removeField(formField)
})
}
function setFieldChecked(
field: UniRadioGroupFieldCtx,
radioChecked: boolean
) {
field.value = {
radioChecked,
value: field.value.value,
}
}
function _resetRadioGroupValue(key: number, change?: boolean) {
fields.forEach((value, index) => {
if (index === key) {
return
}
if (change) {
setFieldChecked(fields[index], false)
}
})
}
return getFieldsValue
return fields
}
......@@ -2,16 +2,20 @@ import {
defineComponent,
inject,
onBeforeUnmount,
Ref,
ref,
computed,
watch,
reactive,
ExtractPropTypes,
} from 'vue'
import { uniLabelKey, UniLabelCtx } from '../label'
import { useListeners } from '../../helpers/useListeners'
import { NVueComponentStyles, createNVueTextVNode } from '../utils'
import { radioProps } from '../../components/radio'
import {
uniRadioGroupKey,
UniRadioGroupCtx,
} from '../../components/radio-group'
import { UniFormCtx, uniFormKey } from '../../components/form'
const radioStyles: NVueComponentStyles = [
{
......@@ -59,8 +63,6 @@ const radioStyles: NVueComponentStyles = [
},
]
type RadioProps = ExtractPropTypes<typeof radioProps>
export default defineComponent({
name: 'Radio',
props: radioProps,
......@@ -68,47 +70,56 @@ export default defineComponent({
emits: ['change'],
setup(props, { slots }) {
const rootRef = ref<HTMLElement | null>(null)
const radioChecked = ref(props.checked)
const radioValue = ref(props.value)
const radioStyle = computed(() => {
const color = props.disabled ? '#adadad' : props.color
if (radioChecked.value) {
return {
backgroundColor: color,
borderColor: color,
}
}
return {
borderColor: '#d1d1d1',
}
})
const reset = () => {
radioChecked.value = false
}
const state = useRadioState(props)
const { uniCheckGroup, uniLabel, field } = useRadioInject(
radioChecked,
radioValue,
reset
)
const onClick = (e: Event, isLabelClick?: boolean) => {
const _onClick = ($event: Event, isLabelClick?: boolean) => {
if (props.disabled) {
return
}
if (isLabelClick) {
rootRef.value!.click()
}
state.radioChecked = !state.radioChecked
/* const formType = props.formType
if (formType) {
if (!uniForm) {
return
}
if (formType === 'submit') {
uniForm.submit(e)
} else if (formType === 'reset') {
uniForm.reset(e)
}
} */
radioChecked.value = !radioChecked.value
uniCheckGroup && uniCheckGroup.radioChange($event, field)
}
const uniLabel = inject<UniLabelCtx>(
uniLabelKey,
false as unknown as UniLabelCtx
)
if (uniLabel) {
uniLabel.addHandler(onClick)
uniLabel.addHandler(_onClick)
onBeforeUnmount(() => {
uniLabel.removeHandler(onClick)
uniLabel.removeHandler(_onClick)
})
}
useListeners(props, { 'label-click': onClick })
useListeners(props, { 'label-click': _onClick })
watch(
[() => props.checked, () => props.value],
([newChecked, newModelValue]) => {
state.radioChecked = newChecked
state.radioValue = newModelValue
radioChecked.value = newChecked
radioValue.value = newModelValue
}
)
......@@ -127,21 +138,20 @@ export default defineComponent({
return () => {
const { disabled } = props
const { radioChecked, radioStyle } = state
return (
<div
ref={rootRef}
{...{ dataUncType: 'uni-radio' }}
onClick={onClick}
onClick={_onClick}
class="uni-radio"
>
<div
style={radioStyle}
style={radioStyle.value}
class="uni-radio-input"
// @ts-expect-error
class={{ 'uni-radio-input-disabled': disabled }}
>
{radioChecked
{radioChecked.value
? createNVueTextVNode('\uEA08', {
class: 'uni-radio-input-icon',
})
......@@ -154,29 +164,49 @@ export default defineComponent({
},
})
function useRadioState(props: RadioProps) {
const radioChecked = ref(props.checked)
const radioValue = ref(props.value)
const radioStyle = computed(() => {
if (radioChecked.value) {
return {
backgroundColor: props.color,
borderColor: props.color,
}
}
return {
borderColor: '#d1d1d1',
}
function useRadioInject(
radioChecked: Ref<string | boolean>,
radioValue: Ref<string>,
reset: () => void
) {
const field = computed({
get: () => ({
radioChecked: Boolean(radioChecked.value),
value: radioValue.value,
}),
set: ({ radioChecked: checked }) => {
radioChecked.value = checked
},
})
const formField = { reset }
const uniCheckGroup = inject<UniRadioGroupCtx>(
uniRadioGroupKey,
false as unknown as UniRadioGroupCtx
)
if (!!uniCheckGroup) {
uniCheckGroup.addField(field)
}
const radioColor = computed(() => (props.disabled ? '#adadad' : props.color))
const uniForm = inject<UniFormCtx>(uniFormKey, false as unknown as UniFormCtx)
if (!!uniForm) {
uniForm.addField(formField)
}
const state = reactive({
radioStyle,
radioColor,
radioChecked,
radioValue,
const uniLabel = inject<UniLabelCtx>(
uniLabelKey,
false as unknown as UniLabelCtx
)
onBeforeUnmount(() => {
uniCheckGroup && uniCheckGroup.removeField(field)
uniForm && uniForm.removeField(formField)
})
return state
return {
uniCheckGroup,
uniForm,
uniLabel,
field,
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册