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

Vue3 Option API问题:父组件无法接收子组件v-model输入值

Nuxt3联系表单:父组件无法接收子组件输入值的解决方案

问题

在Nuxt3项目中,使用自定义输入组件UtilityMainInput与父组件通过v-model绑定表单字段后,提交时父组件的form对象所有值始终为null,无法获取用户输入内容。

原因

Vue3(Nuxt3基于Vue3)对自定义组件的v-model实现做了调整:

  • 不再默认使用value prop和input事件,而是改用modelValue prop和update:modelValue事件
  • 你的子组件仍沿用Vue2的v-model实现方式,导致父组件无法接收到子组件的输入更新

修复步骤

1. 修改子组件UtilityMainInput适配Vue3规范

将原有的value prop替换为modelValue,并把input事件改为update:modelValue:

修复后的子组件代码

<template>
  <div class="normal-form">
    <label :for="name" class="label">
      {{ name }}
    </label>

    <!-- text input -->
    <input 
      v-if="controlType === 'input' && inputType ==='text'" 
      type="text" 
      maxlength="50"
      :name="name" 
      :value="modelValue" 
      @input="$emit('update:modelValue', $event.target.value)">
    <!-- email input -->
    <input 
      v-if="controlType === 'input' && inputType ==='email'" 
      type="email" 
      :name="name" 
      :value="modelValue" 
      @input="$emit('update:modelValue', $event.target.value)">
    <!-- textarea input -->
    <div class="textarea" v-if="controlType === 'textarea'">
      <textarea  
        :name="name" 
        :value="modelValue"
        @input="$emit('update:modelValue', $event.target.value)">
      </textarea>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    name: {
      type: String,
      required: true
    },
    placeholder: {
      type: String,
      required: false,
      default: "text goes here"
    },
    inputType: {
      type: String,
      required: false,
      default: "text"
    },
    controlType: {
      type: String,
      required: false,
      default: 'input'
    },
    modelValue: { // 替换原有的value prop
      type: String,
      default: ''
    }
  },
}
</script>

2. (可选)子组件改用<script setup>语法(更贴合Nuxt3)

如果想使用Nuxt3推荐的<script setup>,子组件可以改成这样:

<template>
  <div class="normal-form">
    <label :for="name" class="label">
      {{ name }}
    </label>

    <!-- text input -->
    <input 
      v-if="controlType === 'input' && inputType ==='text'" 
      type="text" 
      maxlength="50"
      :name="name" 
      :value="modelValue" 
      @input="$emit('update:modelValue', $event.target.value)">
    <!-- email input -->
    <input 
      v-if="controlType === 'input' && inputType ==='email'" 
      type="email" 
      :name="name" 
      :value="modelValue" 
      @input="$emit('update:modelValue', $event.target.value)">
    <!-- textarea input -->
    <div class="textarea" v-if="controlType === 'textarea'">
      <textarea  
        :name="name" 
        :value="modelValue"
        @input="$emit('update:modelValue', $event.target.value)">
      </textarea>
    </div>
  </div>
</template>

<script setup>
const props = defineProps({
  name: {
    type: String,
    required: true
  },
  placeholder: {
    type: String,
    required: false,
    default: "text goes here"
  },
  inputType: {
    type: String,
    required: false,
    default: "text"
  },
  controlType: {
    type: String,
    required: false,
    default: 'input'
  },
  modelValue: {
    type: String,
    default: ''
  }
})
</script>

3. 父组件修正ref一致性问题

父组件中模板的表单ref为formm,但脚本里定义的是formElement,可以修正为统一命名:

<script setup>
import { ref } from 'vue';
const formm = ref(null); // 修正为和模板ref一致

const errorMessage = ref(null);
const form = ref({
    name: null,
    subject: null,
    email: null,
    message: null
});

// ... 其余submitForm和formSubmit函数保持不变
</script>

父组件的v-model绑定无需修改,Vue3会自动映射到子组件的modelValue和update:modelValue事件。

验证

修改完成后,输入表单内容并提交,父组件的form对象会正确获取到子组件的输入值,提交逻辑可以正常执行。

内容的提问来源于stack exchange,提问作者Opeyemi Odedeyi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 05:27:49