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

Svelte条件渲染异常:登录页Header与Drawer短暂显示后消失

问题:SvelteKit中Login页面加载时Header和Drawer短暂显示后消失

我在Svelte项目里有个login页面,全局默认展示Drawer和Header,但想访问login页时隐藏这俩元素。于是在+layout.svelte里加了条件判断:用$app/stores的page获取当前路径,和禁用页面数组比对后,通过visibleDrawer、visibleHeader控制显示。但加载login页时,Header和Drawer会先闪一下再消失,这是为啥?

我的代码如下:

<script>
    import {page} from '$app/stores';
    import "../app.css";
    import Alert from "../lib/components/Alert.svelte";
    import SidebarMenu from "../lib/layout/SidebarMenu.svelte";
    import {onMount} from "svelte";

    let currentPage;
    let visibleDrawer = true;
    let visibleHeader = true;

    const noDrawerPages = [
        "pos",
        "login",
    ];

    const noHeaderPages = [
        "login",
    ];

    onMount(() => {
        visibleDrawer = displayDrawer();
        visibleHeader = displayHeader();

        console.log("displace drawer", visibleDrawer)
        console.log("visible headers", visibleHeader)
    });

    const displayDrawer = () => {
        const strippedPageName = currentPage.replace("/", "");
        return !noDrawerPages.includes(strippedPageName);
    }

    const displayHeader = () => {
        const strippedPageName = currentPage.replace("/", "");
        return !noHeaderPages.includes(strippedPageName);
    }

    $: currentPage = $page.url.pathname;
    $: showDrawerClass = visibleDrawer ? "drawer lg:drawer-open" : "";

</script>

<div id="app">

    <div class=" { showDrawerClass }" >

        <input id="main-drawer" type="checkbox" class="drawer-toggle"/>
        <div class="drawer-content flex flex-col">

            <div class="text-gray-800 w-full">
                {#if visibleHeader}
                    <div>Header</div>
                {/if}
            </div>

            <main class="items-center min-h-screen justify-center w-full pt-12 p-12 border-accent-content/5 bg-gray-100">
                <Alert />
                <slot/>
            </main>

        </div>

        {#if visibleDrawer}
        <SidebarMenu />
            {/if}

    </div>

</div>

问题原因

核心问题出在初始值设置和响应式依赖缺失:

  1. 你给visibleDrawer和visibleHeader设了初始值true,组件第一次渲染时会直接显示Header和Drawer;
  2. onMount是组件挂载到DOM后才执行的钩子,这时候才会计算并更新显示状态,所以会出现“先显示再消失”的闪烁;
  3. 虽然你监听了$page变化更新currentPage,但visibleDrawer和visibleHeader并没有和currentPage建立响应式关联,只有onMount会触发一次计算,逻辑不完整。

解决方案

把visibleDrawer和visibleHeader改成响应式变量,直接依赖currentPage,移除onMount里的逻辑:

修改后的代码:

<script>
    import {page} from '$app/stores';
    import "../app.css";
    import Alert from "../lib/components/Alert.svelte";
    import SidebarMenu from "../lib/layout/SidebarMenu.svelte";

    let currentPage;

    const noDrawerPages = [
        "pos",
        "login",
    ];

    const noHeaderPages = [
        "login",
    ];

    const displayDrawer = (pagePath) => {
        const strippedPageName = pagePath.replace("/", "");
        return !noDrawerPages.includes(strippedPageName);
    }

    const displayHeader = (pagePath) => {
        const strippedPageName = pagePath.replace("/", "");
        return !noHeaderPages.includes(strippedPageName);
    }

    $: currentPage = $page.url.pathname;
    $: visibleDrawer = displayDrawer(currentPage);
    $: visibleHeader = displayHeader(currentPage);
    $: showDrawerClass = visibleDrawer ? "drawer lg:drawer-open" : "";

</script>

<div id="app">
    <div class=" { showDrawerClass }" >
        <input id="main-drawer" type="checkbox" class="drawer-toggle"/>
        <div class="drawer-content flex flex-col">
            <div class="text-gray-800 w-full">
                {#if visibleHeader}
                    <div>Header</div>
                {/if}
            </div>
            <main class="items-center min-h-screen justify-center w-full pt-12 p-12 border-accent-content/5 bg-gray-100">
                <Alert />
                <slot/>
            </main>
        </div>
        {#if visibleDrawer}
            <SidebarMenu />
        {/if}
    </div>
</div>

关键改动

  • 移除onMount钩子,不需要等到挂载后才计算显示状态;
  • 将visibleDrawer和visibleHeader改为响应式变量,依赖currentPage自动更新;
  • 调整displayDrawer和displayHeader函数,直接接收路径参数,逻辑更独立清晰。

这样修改后,组件初始渲染时就会根据当前路径计算出正确的显示状态,不会出现闪烁,同时路由切换时也能自动更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 00:07:05