Skip to content

Commit

Permalink
refactor(components): [radio] switch to script-setup synatx (#7701)
Browse files Browse the repository at this point in the history
* refactor: radio script setup

* refactor: radio script setup
  • Loading branch information
chenxch committed May 17, 2022
1 parent 76f6bd2 commit b0646b3
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 143 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ describe('Radio', () => {
expect(wrapper.classes()).toContain('is-bordered')
})

test('disabled', async () => {
test('change event', async () => {
const wrapper = _mount(
`<el-radio
v-model="radio"
Expand Down
2 changes: 2 additions & 0 deletions packages/components/radio/src/radio-button.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { buildProps } from '@element-plus/utils'
import { radioPropsBase } from './radio'
import type { ExtractPropTypes } from 'vue'
import type RadioButton from './radio-button.vue'

export const radioButtonProps = buildProps({
...radioPropsBase,
Expand All @@ -11,3 +12,4 @@ export const radioButtonProps = buildProps({
} as const)

export type RadioButtonProps = ExtractPropTypes<typeof radioButtonProps>
export type RadioButtonInstance = InstanceType<typeof RadioButton>
53 changes: 16 additions & 37 deletions packages/components/radio/src/radio-button.vue
Original file line number Diff line number Diff line change
Expand Up @@ -30,51 +30,30 @@
</span>
</label>
</template>
<script lang="ts">
import { computed, defineComponent } from 'vue'
<script lang="ts" setup>
import { computed } from 'vue'
import { useNamespace } from '@element-plus/hooks'
import { useRadio } from './radio'
import { radioButtonProps } from './radio-button'
import type { CSSProperties } from 'vue'
export default defineComponent({
defineOptions({
name: 'ElRadioButton',
props: radioButtonProps,
})
setup(props, { emit }) {
const ns = useNamespace('radio')
const {
radioRef,
isGroup,
focus,
size,
disabled,
tabIndex,
modelValue,
radioGroup,
} = useRadio(props, emit)
const props = defineProps(radioButtonProps)
const activeStyle = computed<CSSProperties>(() => {
return {
backgroundColor: radioGroup?.fill || '',
borderColor: radioGroup?.fill || '',
boxShadow: radioGroup?.fill ? `-1px 0 0 0 ${radioGroup.fill}` : '',
color: radioGroup?.textColor || '',
}
})
const ns = useNamespace('radio')
const { radioRef, focus, size, disabled, modelValue, radioGroup } =
useRadio(props)
return {
ns,
isGroup,
size,
disabled,
tabIndex,
modelValue,
focus,
activeStyle,
radioRef,
radioGroup,
}
},
const activeStyle = computed<CSSProperties>(() => {
return {
backgroundColor: radioGroup?.fill || '',
borderColor: radioGroup?.fill || '',
boxShadow: radioGroup?.fill ? `-1px 0 0 0 ${radioGroup.fill}` : '',
color: radioGroup?.textColor || '',
}
})
</script>
2 changes: 2 additions & 0 deletions packages/components/radio/src/radio-group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { buildProps } from '@element-plus/utils'
import { useSizeProp } from '@element-plus/hooks'
import { radioEmits } from './radio'
import type { ExtractPropTypes } from '@vue/runtime-core'
import type RadioGroup from './radio-group.vue'

export const radioGroupProps = buildProps({
id: {
Expand Down Expand Up @@ -35,3 +36,4 @@ export type RadioGroupProps = ExtractPropTypes<typeof radioGroupProps>

export const radioGroupEmits = radioEmits
export type RadioGroupEmits = typeof radioGroupEmits
export type RadioGroupInstance = InstanceType<typeof RadioGroup>
102 changes: 36 additions & 66 deletions packages/components/radio/src/radio-group.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,14 @@
:class="ns.b('group')"
role="radiogroup"
:aria-label="!isLabeledByFormItem ? label || 'radio-group' : undefined"
:aria-labelledby="isLabeledByFormItem ? formItem.labelId : undefined"
:aria-labelledby="isLabeledByFormItem ? formItem!.labelId : undefined"
>
<slot />
</div>
</template>

<script lang="ts">
import {
computed,
defineComponent,
nextTick,
onMounted,
provide,
reactive,
ref,
toRefs,
watch,
} from 'vue'
<script lang="ts" setup>
import { nextTick, onMounted, provide, reactive, ref, toRefs, watch } from 'vue'
import { UPDATE_MODEL_EVENT } from '@element-plus/constants'
import { radioGroupKey } from '@element-plus/tokens'
import {
Expand All @@ -34,64 +24,44 @@ import { debugWarn } from '@element-plus/utils'
import { radioGroupEmits, radioGroupProps } from './radio-group'
import type { RadioGroupProps } from '..'
let id = 1
export default defineComponent({
defineOptions({
name: 'ElRadioGroup',
props: radioGroupProps,
emits: radioGroupEmits,
setup(props, ctx) {
const ns = useNamespace('radio')
const radioGroupRef = ref<HTMLDivElement>()
const { formItem } = useFormItem()
const { inputId: groupId, isLabeledByFormItem } = useFormItemInputId(
props,
{
formItemContext: formItem,
}
)
const changeEvent = (value: RadioGroupProps['modelValue']) => {
ctx.emit(UPDATE_MODEL_EVENT, value)
nextTick(() => ctx.emit('change', value))
}
})
onMounted(() => {
const radios =
radioGroupRef.value!.querySelectorAll<HTMLInputElement>('[type=radio]')
const firstLabel = radios[0]
if (!Array.from(radios).some((radio) => radio.checked) && firstLabel) {
firstLabel.tabIndex = 0
}
})
const props = defineProps(radioGroupProps)
const emit = defineEmits(radioGroupEmits)
const randomName = `el-radio-group-${id++}`
const ns = useNamespace('radio')
const radioGroupRef = ref<HTMLDivElement>()
const { formItem } = useFormItem()
const { inputId: groupId, isLabeledByFormItem } = useFormItemInputId(props, {
formItemContext: formItem,
})
const name = computed(() => {
return props.name || randomName
})
const changeEvent = (value: RadioGroupProps['modelValue']) => {
emit(UPDATE_MODEL_EVENT, value)
nextTick(() => emit('change', value))
}
provide(
radioGroupKey,
reactive({
...toRefs(props),
changeEvent,
name,
})
)
onMounted(() => {
const radios =
radioGroupRef.value!.querySelectorAll<HTMLInputElement>('[type=radio]')
const firstLabel = radios[0]
if (!Array.from(radios).some((radio) => radio.checked) && firstLabel) {
firstLabel.tabIndex = 0
}
})
watch(
() => props.modelValue,
() => formItem?.validate('change').catch((err) => debugWarn(err))
)
provide(
radioGroupKey,
reactive({
...toRefs(props),
changeEvent,
})
)
return {
ns,
radioGroupRef,
formItem,
groupId,
isLabeledByFormItem,
}
},
})
watch(
() => props.modelValue,
() => formItem?.validate('change').catch((err) => debugWarn(err))
)
</script>
12 changes: 8 additions & 4 deletions packages/components/radio/src/radio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { UPDATE_MODEL_EVENT } from '@element-plus/constants'
import { radioGroupKey } from '@element-plus/tokens'
import { useDisabled, useSize, useSizeProp } from '@element-plus/hooks'
import type { ExtractPropTypes, SetupContext } from 'vue'
import type Radio from './radio.vue'

export const radioPropsBase = buildProps({
size: useSizeProp,
Expand All @@ -13,6 +14,7 @@ export const radioPropsBase = buildProps({
default: '',
},
})

export const radioProps = buildProps({
...radioPropsBase,
modelValue: {
Expand All @@ -25,19 +27,17 @@ export const radioProps = buildProps({
},
border: Boolean,
} as const)
export type RadioProps = ExtractPropTypes<typeof radioProps>

export const radioEmits = {
[UPDATE_MODEL_EVENT]: (val: string | number | boolean) =>
isString(val) || isNumber(val) || isBoolean(val),
change: (val: string | number | boolean) =>
isString(val) || isNumber(val) || isBoolean(val),
}
export type RadioEmits = typeof radioEmits

export const useRadio = (
props: { label: RadioProps['label']; modelValue?: RadioProps['modelValue'] },
emit: SetupContext<RadioEmits>['emit']
emit?: SetupContext<RadioEmits>['emit']
) => {
const radioRef = ref<HTMLInputElement>()
const radioGroup = inject(radioGroupKey, undefined)
Expand All @@ -50,7 +50,7 @@ export const useRadio = (
if (isGroup.value) {
radioGroup!.changeEvent(val)
} else {
emit(UPDATE_MODEL_EVENT, val)
emit && emit(UPDATE_MODEL_EVENT, val)
}
radioRef.value!.checked = props.modelValue === props.label
},
Expand All @@ -76,3 +76,7 @@ export const useRadio = (
modelValue,
}
}

export type RadioProps = ExtractPropTypes<typeof radioProps>
export type RadioEmits = typeof radioEmits
export type RadioInstance = InstanceType<typeof Radio>
49 changes: 14 additions & 35 deletions packages/components/radio/src/radio.vue
Original file line number Diff line number Diff line change
Expand Up @@ -38,46 +38,25 @@
</label>
</template>
<script lang="ts">
import { defineComponent, nextTick } from 'vue'
<script lang="ts" setup>
import { nextTick } from 'vue'
import { useNamespace } from '@element-plus/hooks'
import { radioEmits, radioProps, useRadio } from './radio'
export default defineComponent({
defineOptions({
name: 'ElRadio',
props: radioProps,
emits: radioEmits,
setup(props, { emit }) {
const ns = useNamespace('radio')
const {
radioRef,
isGroup,
radioGroup,
focus,
size,
disabled,
tabIndex,
modelValue,
} = useRadio(props, emit)
})
function handleChange() {
nextTick(() => emit('change', modelValue.value))
}
const props = defineProps(radioProps)
const emit = defineEmits(radioEmits)
return {
ns,
focus,
isGroup,
radioGroup,
modelValue,
tabIndex,
size,
disabled,
radioRef,
const ns = useNamespace('radio')
const { radioRef, radioGroup, focus, size, disabled, modelValue } = useRadio(
props,
emit
)
handleChange,
}
},
})
function handleChange() {
nextTick(() => emit('change', modelValue.value))
}
</script>

0 comments on commit b0646b3

Please sign in to comment.