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

Vue3 Options API:如何用v-model关联表单子组件与父组件对象?

问题描述

我按照Vue官方文档的子组件表单v-model参数说明写了代码,目前App.vue通过v-model:first-name和v-model:last-name把父组件的firstLast对象的first、last属性分别绑定到UserName.vue的两个输入框,代码能正常运行。但我想让UserName.vue里用一个包含两个属性的对象来处理,而不是两个单独的变量,该怎么改?


现有代码

App.vue

<script>
import UserName from './UserName.vue'

export default {
  components: { UserName },
  data() {
    return {
      firstLast: {
        first: 'John',
        last: 'Doe'
      }
    }
  }
}
</script>

<template>
  <h1>{{ firstLast.first }} {{ firstLast.last }}</h1>
  <UserName
    v-model:first-name="firstLast.first"
    v-model:last-name="firstLast.last"
  />
</template>

UserName.vue

<script>
export default {
  props: {
    firstName: String,
    lastName: String
  },
  emits: ['update:firstName', 'update:lastName']
}
</script>

<template>
  <input
    type="text"
    :value="firstName"
    @input="$emit('update:firstName', $event.target.value)"
  />
  <input
    type="text"
    :value="lastName"
    @input="$emit('update:lastName', $event.target.value)"
  />
</template>

修改方案

核心是把多个单独的prop合并成一个对象类型的prop,同时调整emit事件和父组件的绑定方式:

1. 修改子组件 UserName.vue

  • 替换原有的两个prop为一个name对象prop,指定类型为Object
  • 将emits改为update:name,用于通知父组件更新整个对象
  • 输入触发时,通过扩展运算符创建新对象(避免直接修改prop),合并更新后的属性再emit给父组件

修改后的代码:

<script>
export default {
  props: {
    name: {
      type: Object,
      required: true,
      // 可选:设置默认值
      default: () => ({ first: '', last: '' })
    }
  },
  emits: ['update:name']
}
</script>

<template>
  <input
    type="text"
    :value="name.first"
    @input="$emit('update:name', { ...name, first: $event.target.value })"
  />
  <input
    type="text"
    :value="name.last"
    @input="$emit('update:name', { ...name, last: $event.target.value })"
  />
</template>

如果需要更严谨的类型校验,可以导入PropType定义对象结构:

import { PropType } from 'vue'

// ...
props: {
  name: {
    type: Object as PropType<{ first: string; last: string }>,
    required: true
  }
}

2. 修改父组件 App.vue

不再使用多个v-model:参数,直接用单个v-model绑定整个firstLast对象即可:

<script>
import UserName from './UserName.vue'

export default {
  components: { UserName },
  data() {
    return {
      firstLast: {
        first: 'John',
        last: 'Doe'
      }
    }
  }
}
</script>

<template>
  <h1>{{ firstLast.first }} {{ firstLast.last }}</h1>
  <UserName v-model="firstLast" />
</template>

内容的提问来源于stack exchange,提问作者Tony Moritz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 12:57:20