You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue3+TS如何通过defineEmits向父组件传递选中的单选框值

Vue3 + TS 单选框子父传值修复方案

你的代码无法正常传值核心是v-model约定不匹配,同时存在类型定义、模板逻辑问题,按以下方式修正即可。

现存问题清单

  • 事件名不匹配:父组件通过v-model="checked"给子组件双向绑值时,Vue3默认要求子组件抛出的更新事件名为update:modelValue,你当前写的update:arrayRadio无法被父组件的v-model识别,值自然无法同步
  • 类型与默认值错误:arrayRadio是对象数组类型,你给的默认值是空字符串,且Props类型直接写any,完全丢失TS类型校验能力
  • 模板逻辑bug:所有单选框的id固定写为html,对应label的for属性全部指向同一个id,点击选项标签无法触发对应单选框选中;用@click事件取值时机过早,容易拿到选中前的旧值
  • 响应式缺失:子组件内部selected变量初始化时直接取props的静态值,没有和父组件的状态做响应式关联

修正后完整代码

父组件

父组件核心逻辑不需要改动,只需要补全子组件的导入即可(setup语法糖下导入后自动注册,不需要写在components配置里)

<script lang="ts">
import { useField, useForm } from 'vee-validate'
import { string } from 'yup'
export default defineComponent({
    components: {},
})
</script>

<script lang="ts" setup>
// 补全子组件导入
import InputRadio from './InputRadio.vue'

const subtitle: string | number = 'Lorem ipsum dolor sit amet consectetur.'
const { handleSubmit, errors } = useForm({
    validationSchema: {
        checked: string().required('enter the field.'),
    },
    initialValues: {
        checked: ''
    },
})
const { value: checked } = useField<string>('checked')
const arrayRadio: { name: string; description: string }[] = [
    {
        name: 'First',
        description: 'Lorem ipsum dolor sit amet consectetur.',
    },
    {
        name: 'Second',
        description: 'Lorem ipsum dolor sit amet consectetur.',
    },
]
</script>

<template>
    <main class="min-h-screen">
        <div class="base-container">Content</div>
        <InputRadio v-model="checked" :array-radio="arrayRadio" />
    </main>
</template>

子组件

修正Props定义、事件名、响应式逻辑和模板id绑定问题:

<script lang="ts" setup>
import { computed, toRefs } from 'vue'

// 定义单选选项的TS类型,移除any
interface RadioOption {
    name: string
    description: string
}

interface Props {
    subtitle?: string
    arrayRadio?: RadioOption[]
    // 增加v-model默认对应的modelValue属性,类型和父组件绑定的checked一致为string
    modelValue?: string
}

const props = withDefaults(defineProps<Props>(), {
    subtitle: '',
    // 引用类型默认值通过工厂函数返回空数组,不能写空字符串
    arrayRadio: () => [],
    modelValue: ''
})

// 修正emit事件名,匹配v-model的默认约定
const emit = defineEmits<{
    (event: 'update:modelValue', value: string): void
}>()

const { arrayRadio, subtitle, modelValue } = toRefs(props)

// 用计算属性做双向代理,不需要单独维护ref,选中值变化自动触发emit
const selected = computed({
    get() {
        return modelValue.value
    },
    set(val: string) {
        emit('update:modelValue', val)
    }
})
</script>

<template>
    <div>
        <div 
            v-for="plan in arrayRadio" 
            :key="plan.name"
            class="mx-auto w-full max-w-md"
        >
            <!-- 动态绑定唯一id,保证label和输入框一一对应 -->
            <input 
                :id="`radio-${plan.name}`" 
                v-model="selected" 
                type="radio" 
                :value="plan.name"
            >
            <label :for="`radio-${plan.name}`">{{ plan.name }}</label>
            <br>
        </div>
    </div>
</template>

内容的提问来源于stack exchange,提问作者Dario Marjanovic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 00:24:24