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

基于Vue3组合式API+TypeScript实现多发票表单数组添加求助

修复后的Vue3 + TypeScript发票多条目表单组件

先上完整修复代码:

<template>
  <div class="invoice-form">
    <div v-for="(invoice, index) in invoices" :key="index" class="invoice-row">
      <div class="form-group">
        <label>发票号码</label>
        <input v-model="invoice.invoiceNumber" type="text" placeholder="请输入发票号码" />
      </div>
      <div class="form-group">
        <label>发票金额</label>
        <input v-model="invoice.amount" type="number" placeholder="请输入发票金额" />
      </div>
      <div class="form-group">
        <label>开票日期</label>
        <input v-model="invoice.invoiceDate" type="date" />
      </div>
      <button 
        type="button" 
        @click="removeRow(index)"
        :disabled="invoices.length <= 1"
      >
        删除
      </button>
    </div>
    <button type="button" @click="addRow" class="add-btn">添加发票</button>
  </div>
</template>

<script setup lang="ts">
import { ref, watch } from 'vue'

// 定义发票数据类型,可根据实际业务字段调整
interface Invoice {
  invoiceNumber: string
  amount: number | string
  invoiceDate: string
}

// 初始化发票数组,默认保留一条空数据,满足单个发票的基础需求
const invoices = ref<Invoice[]>([{
  invoiceNumber: '',
  amount: '',
  invoiceDate: ''
}])

// 添加发票行:直接向数组推入空发票对象即可
const addRow = () => {
  invoices.value.push({
    invoiceNumber: '',
    amount: '',
    invoiceDate: ''
  })
}

// 删除发票行:仅当数组长度大于1时允许删除,避免空数组
const removeRow = (index: number) => {
  if (invoices.value.length > 1) {
    invoices.value.splice(index, 1)
  }
}

// 若需作为子组件配合父组件v-model使用,定义对应emit
const emit = defineEmits<{
  'update:modelValue': [value: Invoice[]]
}>()

// 监听发票数组变化,同步给父组件
watch(invoices, (newVal) => {
  emit('update:modelValue', newVal)
}, { deep: true })
</script>

<style scoped>
.invoice-row {
  display: flex;
  gap: 1rem;
  margin-bottom: 1rem;
  align-items: end;
}
.form-group {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}
.add-btn {
  margin-top: 1rem;
}
</style>

关键修复点说明

  • TypeScript类型约束:新增Invoice接口明确发票字段类型,给invoices数组指定泛型,避免类型模糊导致的绑定错误。
  • 初始化逻辑修正:默认初始化包含一个空发票对象的数组,既满足单个发票的需求,也避免数组为空引发的渲染异常。
  • addRow函数修复:无需传入参数,直接向响应式数组推入空发票对象即可,解决原函数无参数的问题。
  • removeRow函数修复:
    • 新增数组长度判断:仅当invoices.length > 1时允许删除,防止删到空数组。
    • 正确使用索引删除:通过splice(index, 1)精准删除对应位置的发票项,替换原错误的对象判断逻辑。
  • v-model绑定修复:每个输入框直接绑定到循环项的对应字段(如invoice.invoiceNumber),利用Vue响应式特性实现双向绑定,确保输入值同步到数组中。
  • 父组件v-model支持:通过defineEmits定义update:modelValue事件,监听数组变化后同步给父组件,实现父子组件的v-model联动。

内容的提问来源于stack exchange,提问作者jean.silva

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 16:55:26