基于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
相关产品推荐
相关产品推荐

