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

Svelte数组元素移除时fly过渡动画异常问题求助

解决Svelte列表元素删除时Fly过渡动画错误问题

问题根源分析

  1. 第一个方案的问题:使用playerIndex作为{#key}的值,当删除元素后,后续元素的索引会自动递减。Svelte的{#each}会复用现有组件,最后一个组件会被销毁,导致过渡动画始终作用在列表最后一项,而非被删除的目标项。

  2. 第二个方案的问题:子组件接收的playerIndex是初始渲染时的值,当列表更新后,子组件的playerIndex并未同步更新,导致setTimeout执行splice时删除了错误的元素;同时子组件的didRemoveElement状态会错误隐藏最后一个DOM元素,和实际数组状态不一致。


正确实现方案

核心思路是使用唯一标识作为{#each}的key,让Svelte能准确识别被删除的元素,而非依赖索引。同时利用Svelte原生过渡系统自动处理动画流程,无需额外的定时器或状态管理。

情况1:玩家名称唯一

<script lang="ts">
    import { fly } from 'svelte/transition';

    let players: string[] = ['Juan', 'John', 'Luis'];
</script>

<div class="overflow-hidden">
    {#each players as player (player)} <!-- 用玩家名称作为唯一key -->
        <div class="flex" out:fly={{ duration: 2000, x: '100vw', opacity: 0 }}>
            <span>{player}</span>
            <button
                on:click={() => {
                    // 用filter做不可变更新,Svelte能精准检测数组变化
                    players = players.filter(p => p !== player);
                }}
            >
                Remove
            </button>
        </div>
    {/each}
</div>

情况2:玩家名称可能重复(推荐用唯一ID)

<script lang="ts">
    import { fly } from 'svelte/transition';

    // 定义带唯一ID的玩家类型
    type Player = { id: number; name: string };
    let players: Player[] = [
        { id: 1, name: 'Juan' },
        { id: 2, name: 'John' },
        { id: 3, name: 'Luis' }
    ];
</script>

<div class="overflow-hidden">
    {#each players as player (player.id)} <!-- 用唯一ID作为key -->
        <div class="flex" out:fly={{ duration: 2000, x: '100vw', opacity: 0 }}>
            <span>{player.name}</span>
            <button
                on:click={() => {
                    players = players.filter(p => p.id !== player.id);
                }}
            >
                Remove
            </button>
        </div>
    {/each}
</div>

方案说明

  • 唯一Key的作用:Svelte通过key识别每个列表项的身份,删除元素时只会销毁对应key的组件,确保过渡动画作用在被删除的目标元素上。
  • 不可变更新数组:用filter替代splice,生成新数组而非修改原数组,让Svelte能准确检测到数组变化,触发正确的DOM更新。
  • 原生过渡系统:out:fly会自动在元素销毁前执行动画,动画完成后再移除DOM,后续元素会自然填充空白区域,完全符合你期望的交互效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 22:05:37