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

Vue3组合式函数问题:输入数据跨组件展示与表单提交

Vue3组合式函数useInput数据共享与表单提交问题解决方案

问题核心原因

  1. 独立状态隔离:每次调用useInput()都会生成全新的ref实例,文本组件、邮箱组件、按钮组件各自持有独立的input状态,按钮里的input是初始空值,自然无法获取邮箱组件的输入内容。
  2. 邮箱组件笔误:邮箱组件的@input绑定了未定义的updateEmailInput函数,导致输入内容根本不会更新到组件内部的input状态。

分步解决方案

1. 先修复邮箱组件的笔误

把邮箱组件里的updateEmailInput改成updateInput,同时给输入框设置唯一ID避免冲突:

<script setup>
import { useInput } from '@/composables/useInput.js'
const [input, updateInput] = useInput()
</script>

<template>
  <div class="input">
    <input
      id="email-input"
      type="email"
      :value="input"
      @input="updateInput($event.target.value)"
    />
  </div>
</template>

2. 父组件统一管理表单状态(核心解决数据共享与提交)

要实现组件间数据同步和表单提交,最合理的方式是让父组件作为状态中心,子组件通过v-model将数据同步到父组件,按钮组件直接从父组件获取所需数据。

优化useInput组合式函数

改用对象返回(避免解构顺序出错,也更易扩展):

// composables/useInput.js
import { ref, watch } from 'vue'

export function useInput(initialValue = '') {
  const input = ref(initialValue)
  
  function updateInput(newInput) {
    input.value = newInput
  }

  return { input, updateInput }
}

父组件定义所有表单状态

<!-- 父组件 -->
<script setup>
import { ref } from 'vue'
import TextInput from './TextInput.vue'
import EmailInput from './EmailInput.vue'
import ButtonComponent from './ButtonComponent.vue'

// 统一管理三个输入框的状态
const textInput1 = ref('')
const textInput2 = ref('')
const emailInput = ref('')

// 表单提交逻辑
function submitForm() {
  const formData = {
    text1: textInput1.value,
    text2: textInput2.value,
    email: emailInput.value
  }
  console.log('提交表单数据:', formData)
  // 这里替换为实际的API请求或提交逻辑
}
</script>

<template>
  <TextInput v-model="textInput1" label="文本输入1" />
  <TextInput v-model="textInput2" label="文本输入2" />
  <EmailInput v-model="emailInput" />
  <ButtonComponent :current-email="emailInput" @submit="submitForm" />
</template>

改造文本输入组件适配v-model

<!-- TextInput.vue -->
<script setup>
import { useInput } from '@/composables/useInput.js'
import { watch } from 'vue'

// 接收父组件的v-model值
const props = defineProps({
  modelValue: String,
  label: String
})
// 触发v-model更新的事件
const emit = defineEmits(['update:modelValue'])

// 初始化useInput
const { input, updateInput } = useInput(props.modelValue)

// 监听输入变化,同步给父组件
watch(input, (newVal) => {
  emit('update:modelValue', newVal)
})
</script>

<template>
  <div>
    <label :for="`input-${label}`">{{ input }}</label>
    <input
      :id="`input-${label}`"
      type="text"
      :value="input"
      @input="updateInput($event.target.value)"
    />
  </div>
</template>

改造邮箱输入组件适配v-model

<!-- EmailInput.vue -->
<script setup>
import { useInput } from '@/composables/useInput.js'
import { watch } from 'vue'

const props = defineProps({
  modelValue: String
})
const emit = defineEmits(['update:modelValue'])

const { input, updateInput } = useInput(props.modelValue)

watch(input, (newVal) => {
  emit('update:modelValue', newVal)
})
</script>

<template>
  <div class="input">
    <input
      id="email-input"
      type="email"
      :value="input"
      @input="updateInput($event.target.value)"
    />
  </div>
</template>

改造按钮组件,接收邮箱值和提交事件

<!-- ButtonComponent.vue -->
<script setup>
const props = defineProps({
  currentEmail: String
})
const emit = defineEmits(['submit'])
</script>

<template>
  <button @click="emit('submit')">
    {{ currentEmail || '请输入邮箱' }} - 提交表单
  </button>
</template>

简化方案(无需useInput)

如果useInput的逻辑很简单,也可以直接用Vue的v-model原生实现,去掉组合式函数,代码更简洁:

<!-- TextInput.vue 简化版 -->
<script setup>
const props = defineProps({
  modelValue: String,
  label: String
})
const emit = defineEmits(['update:modelValue'])
</script>

<template>
  <div>
    <label :for="`input-${label}`">{{ modelValue }}</label>
    <input
      :id="`input-${label}`"
      type="text"
      :value="modelValue"
      @input="emit('update:modelValue', $event.target.value)"
    />
  </div>
</template>

关键知识点

  • 组合式函数每次调用都会创建独立的状态,适合封装组件内部的复用逻辑,但不适合跨组件共享状态。
  • 跨组件共享状态的最佳实践是状态提升,把状态放到共同的父组件中,通过props和事件传递数据。
  • Vue的v-model是语法糖,本质是modelValue prop + update:modelValue事件,适合实现双向绑定。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 08:02:33