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

SvelteKit图片轮播{#each}渲染时fade过渡动画不生效问题

问题根源

过渡不生效核心是2个问题:

  • {#each}循环没有指定唯一key:Svelte默认按列表位置对比DOM变化,你每次切片后永远只返回1个img元素,Svelte会判定为「同一个DOM节点仅修改了src属性」,不会触发元素创建/销毁对应的过渡动画,直接替换图片资源导致闪烁。
  • 切片逻辑的初始值和切换逻辑不匹配:初始selected=1、prevSelected=0时slice(0,1)仅返回索引为0的图片,切换时新旧图片没有同时存在的过渡窗口,旧图直接被移除出新数组,新图直接替换位置。
    另外你引入了slide过渡但没有使用,属于冗余代码不影响功能。
修复方案
  1. 给{#each}循环添加唯一key,用图片自带的Index字段作为唯一标识,让Svelte能正确追踪每个图片元素的增删
  2. 单图切换的淡入淡出效果用{#key}块实现更简洁,绑定当前选中的图片索引后,每次索引变化会自动销毁旧元素、创建新元素,触发过渡
  3. 修正索引判断逻辑,避免数组越界
修复后可运行代码
<script>
    import { fade } from 'svelte/transition';
    let images = [
        {
            Index: 0,
            src: 'src/images/img2.jpeg',
            alt: 'znaki ewakuacyjne',
            class: 'show'
        },
        {
            Index: 1,
            src: 'src/images/img3.jpeg',
            alt: 'buty',
            class: ''
        },
        {
            Index: 2,
            src: 'src/images/img4.jpeg',
            alt: 'znaki informacyjne',
            class: ''
        }
    ];
    // 初始默认显示第一张图,索引从0开始
    let selected = 0;

    function handleClick() {
        if (selected >= images.length - 1) {
            return;
        }
        selected += 1;
    }
    function handleBack() {
        if (selected <= 0) {
            return;
        }
        selected -= 1;
    }
</script>

<h3 class="text-center font-semibold text-xl m-3">Galeria</h3>
<div class="image-gallery flex flex-col justify-center items-center">
    <!-- 用key块绑定选中索引,变化时自动触发过渡 -->
    {#key selected}
        <img
            transition:fade
            src={images[selected].src}
            alt={images[selected].alt}
            class="h-80 w-50 rounded-lg"
        />
    {/key}
    <div class="flex flex-row gap-12">
        <button
            on:click={handleBack}
            type="button"
            class="text-white bg-red-700 hover:bg-red-800 focus:outline-none focus:ring-4 focus:ring-red-300 font-medium rounded-full text-sm px-5 py-2.5 text-center mr-2 mb-2 dark:bg-red-600 dark:hover:bg-red-700 dark:focus:ring-red-900 m-3"
            >⬅️</button
        >
        <button
            on:click={handleClick}
            type="button"
            class="text-white bg-blue-700 hover:bg-blue-800 focus:outline-none focus:ring-4 focus:ring-blue-300 font-medium rounded-full text-sm px-5 py-2.5 text-center mr-2 mb-2 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800 m-3"
            >➡️</button
        >
    </div>
</div>

<style lang="scss">
</style>

如果你要保留each加切片的实现方式,只需要给each加唯一key即可,写法为:

{#if shown}
{#each images.slice(prevSelected, selected) as img (img.Index)}
    <img
        transition:fade
        src={img.src}
        alt={img.alt}
        class="h-80 w-50 rounded-lg"
    />
{/each}
{/if}

注意:这种切片写法下,切换时旧图和新图的切片范围没有重叠,旧图会执行淡出、新图同时执行淡入,需要给图片容器加固定高度避免布局抖动。

Tailwind CSS本身不会干扰Svelte过渡效果,不需要额外调整配置。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 05:45:41