在SvelteKit中实现表单Action触发的加载Spinner
问题
我有一个包含邮箱、密码和确认密码的简单表单,使用SvelteKit的Action处理提交。基于PocketBase数据库,我希望在以下两个阶段触发加载Spinner:1. 检查数据库中是否已存在该用户;2. 若用户不存在则执行注册流程。我尝试在Action中设置isLoading布尔值标记加载状态,但无法在客户端获取该状态的初始及更新值;曾尝试使用Store,却发现Store无法在服务端与客户端之间共享状态。请问有什么可行的替代方案?
以下是我的Action代码:
import { superValidate } from 'sveltekit-superforms/server'; import { redirect } from '@sveltejs/kit'; import { fail } from '@sveltejs/kit'; import { loginSchema } from '$lib/schema/zodschema'; import { ClientResponseError } from 'pocketbase'; export const load = async () => { const form = await superValidate(loginSchema); return { form }; }; export const actions = { default: async ({ locals, request }) => { const form = await superValidate(request, loginSchema); try { const { email } = form.data const records = await locals.pb.collection('test').getFullList(); const userRecords = records.filter(value => value.email === form.data.email); if (userRecords.length > 0) { const existingUser = userRecords[0] if (existingUser && existingUser.verified) { return { accountCreated: false, message: 'The user records exists. Proceed to login instead', isVerified: true, } } else { return { accountCreated: false, message: 'The user record exists. You have to verify to access', isVerified: false, } } } else { await locals.pb.collection('test').create(form.data); return { accountCreated: true, message: 'The user record is successfully created', isVerified: false, } } } catch (error) { // Handle the error if (error instanceof ClientResponseError) { return { error: error.message, isLoading: false } } } } };
我曾尝试设置let isLoading = true并在不同阶段设为false,但核心问题是如何在客户端获取该状态。
解决方案
方法一:用SvelteKit内置的use:enhance跟踪提交状态
不需要在服务端传递isLoading,直接在客户端通过表单钩子监听提交流程:
<script> import { enhance } from '$app/forms'; let isLoading = false; </script> <form method="POST" use:enhance={({ cancel }) => { isLoading = true; // 提交开始时激活加载状态 return async ({ update }) => { await update(); // 等待服务端Action处理完成 isLoading = false; // 处理结束后关闭加载 }; }}> <!-- 邮箱、密码等表单输入框 --> {#if isLoading} <div>加载中...</div> {/if} <button type="submit" disabled={isLoading}>提交</button> </form>
这个逻辑会覆盖你需要的两个阶段——检查用户存在性、注册流程,因为这两个步骤都属于服务端Action的处理周期,提交开始就显示加载,结束后自动隐藏。
方法二:利用Superforms的内置loading状态
既然你已经在用superValidate,Superforms本身提供了现成的加载状态,不用额外维护:
<script> import { superForm } from 'sveltekit-superforms/client'; export let data; const { form, enhance } = superForm(data.form); </script> <form method="POST" use:enhance> <!-- 表单元素 --> {#if form.loading} <div>加载中...</div> {/if} <button type="submit" disabled={form.loading}>提交</button> </form>
form.loading会在表单提交到服务端的过程中自动变为true,处理完成后恢复false,完全匹配你的需求,而且不需要修改服务端Action代码。
额外优化:提升服务端查询效率
你当前用getFullList()全量拉取数据再过滤的方式,用户量上来后会很慢,建议改用PocketBase的精准查询:
// 替换原Action中的用户查询逻辑 try { // 直接查询匹配邮箱的用户 const existingUser = await locals.pb.collection('test').getFirstListItem(`email = "${form.data.email}"`); // 原有的已存在用户判断逻辑 if (existingUser.verified) { return { accountCreated: false, message: 'The user records exists. Proceed to login instead', isVerified: true }; } else { return { accountCreated: false, message: 'The user record exists. You have to verify to access', isVerified: false }; } } catch (error) { if (error instanceof ClientResponseError && error.status === 404) { // 404表示用户不存在,执行注册 await locals.pb.collection('test').create(form.data); return { accountCreated: true, message: 'The user record is successfully created', isVerified: false }; } // 处理其他错误 return { error: error.message }; }
内容的提问来源于stack exchange,提问作者jeff
相关产品推荐
相关产品推荐

