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

SvelteKit布局中{#key}包裹的<slot>页面过渡未延迟如何解决?

解决SvelteKit页面过渡时内容提前更新的问题

问题核心在于SvelteKit的路由导航会即时替换<slot>内容,和{#key}的过渡触发同步,导致旧内容还未完成淡出,新内容就已显示。要实现「旧页面淡出→新页面淡入」的顺序,需拦截导航流程,等待过渡完成后再加载新页面。

修改+layout.svelte代码如下:

<script lang="ts">
    import '$lib/style.css';
    import { page } from '$app/stores';
    import { fade } from 'svelte/transition';
    import { goto, onNavigate } from '$app/navigation';
    import { writable } from 'svelte/store';

    // 延迟更新页面路径,等待过渡完成
    const currentPath = writable($page.url.pathname);
    let isTransitioning = false;

    onNavigate(async ({ from, to, cancel }) => {
        if (isTransitioning || from?.url.pathname === to?.url.pathname) return;
        
        // 阻止默认导航行为
        cancel();
        isTransitioning = true;

        // 触发旧内容淡出动画
        currentPath.set(from.url.pathname);
        
        // 等待淡出动画完成(时长与out:fade配置一致)
        await new Promise(resolve => setTimeout(resolve, 1000));

        // 执行导航并更新路径,触发新内容淡入
        await goto(to.url.pathname);
        currentPath.set(to.url.pathname);
        isTransitioning = false;
    });
</script>

<div class="page">
    <div class="bar">
        Sidebar
        <a href="/">Page 1</a>
        <a href="/page2">Page 2</a>
    </div>

    <div class="content-wrapper">
        {#key $currentPath}
            <div class="content" 
                 in:fade={{ duration: 1000 }} 
                 out:fade={{ duration: 1000 }}>
                <div class="title">
                    {$currentPath}
                </div>
                <slot />
            </div>
        {/key}
    </div>
</div>

<style global>
    .page {
        display: flex;
        flex-direction: row;
        box-sizing: border-box;
        width: 100vw;
        min-height: 100vh;
    }

    .bar {
        display: flex;
        flex-direction: column;
        width: 300px;
        color: white;
        background: black;
    }

    a {
        color: white;
    }

    .content-wrapper {
        flex-grow: 1;
        width: 100%;
        min-height: 100vh;
        position: relative;
    }

    .content {
        position: absolute;
        width: 100%;
        height: 100%;
    }

    .title {
        font-size: 2em;
    }
</style>

关键修改说明:

  • 新增currentPath存储,用来延迟更新页面路径,避免路由即时替换slot内容
  • 通过onNavigate拦截默认导航,等待旧页面淡出动画完成后再执行实际导航
  • 给.content添加position: absolute,确保新旧页面过渡时不会互相挤压
  • 移除in:fade的delay配置,因为现在是旧页面完全淡出后才触发新页面淡入,无需额外延迟

修改后,导航时会先完成旧页面的淡出动画,再加载新页面并执行淡入,<slot>内容即可和标题同步正常过渡。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 23:50:35