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

Vue中如何处理含多内嵌表单行的表格及Inertia表单绑定问题

问题根因
  • 你仅创建了1个全局共享的Inertia form实例,v-for渲染的所有行表单都绑定到这同一个实例,无法区分不同行的账单数据
  • bills.value是后端返回的账单数组,数组本身不存在amount、goal_id属性,直接读取这两个值必然返回undefined
  • 循环渲染的隐藏input存在全局id重复问题,且你没有把每行对应的账单值和表单做对应绑定,提交时自然拿不到正确数据
  • 你重复定义了两次账单数据源:既通过defineProps声明接收父组件传入的pendingBills,又通过usePage重复从页面props取数,容易造成数据源混乱
实现方案

不需要为每一行单独创建form实例(会造成不必要的内存开销),保留单个form实例即可,提交时直接传入当前行的账单数据赋值给form,天然满足「同一时间仅能触发一个提交」的需求,具体改动如下:

  • 移除循环内冗余的重复id隐藏input(Inertia useForm提交时直接读取响应式对象的字段值,不需要依赖DOM input元素传值)
  • 初始化form时不需要提前绑定账单数据,字段留空即可
  • 提交事件直接传入当前循环的bill对象,在提交逻辑内给form字段赋值后再发起请求
  • 统一使用单一数据源,去掉重复的账单数据读取逻辑

修正后完整代码

<template>
    <jet-action-section>
        <template #title>
            Pending Bills
        </template>

        <template #description>
            A list of all pending payments.
        </template>

        <template #content>
            <h3 class="text-sm font-medium text-gray-900 dark:text-gray-200" v-if="pendingBills.length > 0">
                Pending Payments.
            </h3>

            <div class="mt-3 max-w-xl text-sm text-gray-600 dark:text-gray-300" v-if="pendingBills.length > 0">
                <div class="p-6 overflow-x-auto">
                    <table class="w-full whitespace-nowrap">
                        <tr class="text-left font-bold text-white">
                            <th class="bg-blue-500 border-4 p-2 rounded">Payment Description</th>
                            <th class="bg-blue-500 border-4 p-2 rounded">Amount</th>
                            <th class="bg-blue-500 border-4 p-2 rounded">Action</th>
                        </tr>
                        <tr v-for="bill in pendingBills" :key="bill.id" class="text-gray-700 dark:text-gray-200 hover:bg-blue-200 dark:hover:bg-blue-300 focus-within:bg-blue-100">
                            <td class="border-2 p-2">{{ bill.message }}</td>
                            <td class="border-2 p-2">₦{{ bill.amount }}</td>
                            <td class="border-2 p-2">
                                <form @submit.prevent="payPerformanceFee(bill)">
                                    <div class="flex items-center justify-end mt-4">
                                        <jet-button class="ml-4" :class="{ 'opacity-25': form.processing }" :disabled="form.processing">
                                            Pay Performance Fee
                                        </jet-button>
                                    </div>
                                </form>
                            </td>
                        </tr>
                    </table>
                </div>
            </div>
            <h3 class="text-sm font-medium text-gray-900 dark:text-gray-200" v-else>
                Payments you're yet to pay will show up here.
            </h3>
        </template>
    </jet-action-section>
</template>

<script setup>
import JetActionSection from '@/Jetstream/ActionSection.vue'
import JetButton from '@/Jetstream/Button.vue'
import { useForm } from '@inertiajs/inertia-vue3'

// 统一使用父组件传入的pendingBills作为数据源,若数据是从Inertia页面props传入则替换为usePage读取逻辑即可
const props = defineProps({
    pendingBills: {
        type: Array,
        required: true
    }
})

const form = useForm({
    amount: null,
    goal_id: null
})

function payPerformanceFee(bill) {
    // 提交前给form字段赋值当前行的账单数据
    form.amount = bill.amount
    form.goal_id = bill.goal_id
    form.post(route('pending.bill'))
}
</script>

说明:因为全局只有一个form实例,提交时form.processing会变为true,所有行的支付按钮都会自动进入禁用状态,天然避免重复提交,完全符合需求。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 08:54:20