SvelteKit表单:如何让每次提交均触发过渡动画
解决SvelteKit表单重复提交相同状态时过渡不触发的问题
问题场景
你有如下SvelteKit表单:
<script lang="ts"> import { fly } from 'svelte/transition'; import { enhance } from '$app/forms'; import type { ActionData } from './$types'; export let form: ActionData; </script> <form method="POST" action="?/login" use:enhance> <input type="email" name="email" placeholder="student@example.edu" /> <button>Register</button> </form> {#if form === 'EMAIL_SENT'} <p>We sent a magic login link to your email!</p> {:else if form === 'EMAIL_INVALID'} <p>Please enter a valid email.</p> {/if}
为提示用户提交结果,你给反馈文本添加了transition:fade,但发现连续提交相同状态(比如两次无效邮箱)时,过渡动画仅触发一次,无法有效提示用户第二次提交仍失败。这是因为Svelte仅在form状态变化时重新渲染元素,相同状态下不会触发过渡逻辑。
解决方案
核心思路是追踪表单提交动作,而非仅依赖form状态,强制反馈元素在每次提交后重新渲染,从而触发过渡动画。
方法一:用计数器配合{#key}块(推荐)
通过计数器记录提交次数,利用{#key}块让Svelte在计数器变化时重建反馈元素:
<script lang="ts"> import { fade } from 'svelte/transition'; import { enhance } from '$app/forms'; import type { ActionData } from './$types'; export let form: ActionData; let submitCount = 0; // 追踪提交次数 const handleFormEnhance = () => { return async ({ update }) => { await update(); submitCount += 1; // 每次提交后更新计数器 }; }; </script> <form method="POST" action="?/login" use:enhance={handleFormEnhance}> <input type="email" name="email" placeholder="student@example.edu" /> <button>Register</button> </form> {#key submitCount} {#if form === 'EMAIL_SENT'} <p transition:fade>We sent a magic login link to your email!</p> {:else if form === 'EMAIL_INVALID'} <p transition:fade>Please enter a valid email.</p> {/if} {/key}
{#key submitCount}会在计数器值变化时,销毁并重新创建内部DOM元素,无论form状态是否改变,过渡动画都会重新触发。
方法二:通过开关状态强制隐藏/显示反馈
如果不想用计数器,也可以在提交时先隐藏反馈,等待DOM更新后再重新显示:
<script lang="ts"> import { fade } from 'svelte/transition'; import { enhance } from '$app/forms'; import { tick } from 'svelte'; import type { ActionData } from './$types'; export let form: ActionData; let showFeedback = false; const handleFormEnhance = () => { return async ({ update }) => { showFeedback = false; // 先隐藏反馈 await tick(); // 等待Svelte完成DOM更新 await update(); // 等待表单动作执行完成 showFeedback = true; // 重新显示反馈 }; }; </script> <form method="POST" action="?/login" use:enhance={handleFormEnhance}> <input type="email" name="email" placeholder="student@example.edu" /> <button>Register</button> </form> {#if showFeedback} {#if form === 'EMAIL_SENT'} <p transition:fade>We sent a magic login link to your email!</p> {:else if form === 'EMAIL_INVALID'} <p transition:fade>Please enter a valid email.</p> {/if} {/if}
通过showFeedback的状态切换,强制反馈元素先销毁再重建,确保每次提交都能触发过渡动画。
内容的提问来源于stack exchange,提问作者Daniel Ting
相关产品推荐
相关产品推荐

