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

SvelteKit中提交表单组件时如何阻止页面刷新?

问题分析与解决方案

核心问题

  1. 全局状态冲突:你用全局的linkType和linkResult变量存储下拉框值,但表格每行是独立条目,共享变量会导致所有行的下拉框值同步,提交时无法正确对应每行的选择。
  2. 下拉框未绑定状态:表格中的下拉框没有绑定到状态变量,也未触发更新事件,导致选择的值无法同步到变量中。
  3. 不必要的默认行为阻止:更新表单中同时使用use:enhance和event.preventDefault(),二者可能冲突,use:enhance本身已阻止页面默认刷新行为。

修复步骤

1. 为每行数据创建独立状态

在#each循环中,为每行声明局部的rowLinkType和rowLinkResult变量,替换全局共享变量:

{#each form.response as row}
    <!-- 为每行创建局部状态 -->
    {#set rowLinkType = row.linkType || ''}
    {#set rowLinkResult = row.linkResult || ''}

    <div class="overflow-x-auto">
        <!-- 表格内容 -->
    </div>
{/each}

2. 绑定下拉框到局部状态

修改表格中的下拉框,添加bind:value绑定到局部变量,无需额外的on:change事件:

<!-- Link Type下拉框 -->
<select
    bind:value={rowLinkType}
    class="block rounded-md border border-gray-300 bg-white px-3 py-2 shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-indigo-500 sm:text-sm"
>
    {#each linkTypes as type}
        <option value={type}>{type}</option>
    {/each}
</select>

<!-- Link Result下拉框 -->
<select
    bind:value={rowLinkResult}
    class="block rounded-md border border-gray-300 bg-white px-3 py-2 shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-indigo-500 sm:text-sm"
>
    {#each linkResults as result}
        <option value={result}>{result}</option>
    {/each}
</select>

3. 修复更新表单

移除on:submit={(event) => event.preventDefault()},并将隐藏输入的值改为局部变量:

<form
    action="?/update"
    method="POST"
    use:enhance
>
    <input type="hidden" value={row.id} name="id" />
    <input type="hidden" value={rowLinkType} name="linkType" />
    <input type="hidden" value={rowLinkResult} name="linkResult" />
    <button
        type="submit"
        class="rounded bg-blue-500 px-4 py-2 text-white hover:bg-blue-700"
    >Update</button>
</form>

4. 移除全局冗余代码

删除全局的linkType、linkResult变量以及对应的handleLinkTypeChange、handleLinkResultChange函数,因为现在每行使用独立状态。

修改后的完整Svelte组件代码

<script>
    import { enhance } from '$app/forms';

    export let data;
    let selectedUser = '';
    let selectedCourse = '';
    function handleUserChange(event) {
        selectedUser = event.target.value;
        selectedCourse = '';
    }
    function handleCourseChange(event) {
        selectedCourse = event.target.value;
    }
    async function showSelection() {
        console.log('Selected User:', selectedUser);
        console.log('Selected Course:', selectedCourse);
    }

    export let form;
    let linkTypes = ['Type1', 'Type'];
    let linkResults = ['Result1', 'Result2'];
</script>

<div>
    <h1 class="text-white-700 text-center text-4xl font-bold">Select Client Data</h1>

    {#if data}
        <form
            action="?/userSelection"
            method="POST"
            use:enhance
            class="flex flex-col items-center space-y-4 p-10"
        >
            <select
                name="user"
                class="select select-accent w-full max-w-xs"
                value={selectedUser}
                on:change={handleUserChange}
            >
                <option disabled selected>Select a User</option>
                {#each data.userData as user}
                    <option value={user.user}>{user.user}</option>
                {/each}
            </select>
            {#if selectedUser !== ''}
                <select
                    name="course"
                    class="select select-accent w-full max-w-xs"
                    value={selectedCourse}
                    on:change={handleCourseChange}
                >
                    <option disabled selected>Select a Course</option>
                    {#each data.userData.find((user) => user.user === selectedUser)?.courses || [] as course}
                        <option value={course}>{course}</option>
                    {/each}
                </select>
            {/if}
            <button type="submit" on:click={showSelection} class="btn btn-primary">Get Data</button>
        </form>
    {:else}
        <p>Loading...</p>
    {/if}

    {#if form && form.response}
        {#each form.response as row}
            {#set rowLinkType = row.linkType || ''}
            {#set rowLinkResult = row.linkResult || ''}
            <div class="overflow-x-auto">
                <table class="min-w-full divide-y divide-gray-200">
                    <thead class="bg-gray-50">
                        <tr>
                            <th
                                scope="col"
                                class="w-1/5 px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500"
                            >ID</th>
                            <th
                                scope="col"
                                class="w-1/5 px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500"
                            >Link</th>
                            <th
                                scope="col"
                                class="w-2/5 px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500"
                            >Link Type</th>
                            <th
                                scope="col"
                                class="w-2/5 px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500"
                            >Link Result</th>
                            <th
                                scope="col"
                                class="w-2/5 px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500"
                            >Update</th>
                        </tr>
                    </thead>
                    <tbody class="divide-y divide-gray-200 bg-white">
                        <tr class="border-b border-gray-200 hover:bg-gray-100">
                            <td class="whitespace-nowrap px-6 py-4">{row.id}</td>
                            <td
                                class="whitespace-nowrap px-6 py-4"
                                style="max-width: 300px; overflow-x: auto; width: 100%;"
                            ><a href={row.url} class="truncate">{row.url}</a></td>
                            <td class="whitespace-nowrap px-6 py-4">
                                <select
                                    bind:value={rowLinkType}
                                    class="block rounded-md border border-gray-300 bg-white px-3 py-2 shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-indigo-500 sm:text-sm"
                                >
                                    {#each linkTypes as type}
                                        <option value={type}>{type}</option>
                                    {/each}
                                </select>
                            </td>
                            <td class="whitespace-nowrap px-6 py-4">
                                <select
                                    bind:value={rowLinkResult}
                                    class="block rounded-md border border-gray-300 bg-white px-3 py-2 shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-indigo-500 sm:text-sm"
                                >
                                    {#each linkResults as result}
                                        <option value={result}>{result}</option>
                                    {/each}
                                </select>
                            </td>
                            <td class="whitespace-nowrap px-6 py-4 text-right">
                                <form
                                    action="?/update"
                                    method="POST"
                                    use:enhance
                                >
                                    <input type="hidden" value={row.id} name="id" />
                                    <input type="hidden" value={rowLinkType} name="linkType" />
                                    <input type="hidden" value={rowLinkResult} name="linkResult" />
                                    <button
                                        type="submit"
                                        class="rounded bg-blue-500 px-4 py-2 text-white hover:bg-blue-700"
                                    >Update</button>
                                </form>
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
        {/each}
    {:else}
        <div><p>Select User First</p></div>
    {/if}
</div>

额外说明

  • #set是Svelte 4+的语法,用于循环内声明局部变量;若使用旧版本,可改用嵌套组件或{@const}实现每行独立状态。
  • 现在每行下拉框值独立存储,use:enhance会正常处理无刷新提交,页面不会再刷新。
  • 若要实际更新PocketBase数据,可修改后端update函数:
update: async ({ request, locals }) => {
    const formData = await request.formData();
    const id = formData.get("id");
    const linkType = formData.get("linkType");
    const linkResult = formData.get("linkResult");
    try {
        await locals.pb.collection("Orbittest").update(id, {
            linkType,
            linkResult
        });
        return { success: true, id };
    } catch (error) {
        console.error("Update error:", error);
        return { error: true, message: error.message };
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 15:18:09