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

直接输入URL或重载时Shallow Routing报404的解决方法

问题现象

  • 点击项目时Shallow Routing工作正常
    点击项目时Shallow Routing工作正常

  • 直接输入项目URL时Shallow Routing报404
    直接输入项目URL时Shallow Routing报404

可复现问题的在线示例

相关代码

src/routes/(news)/+layout.svelte

<script lang="ts">
import './../../app.css'
import { page } from '$app/stores';
import { pushState } from '$app/navigation';
import { MediaQuery } from 'svelte/reactivity';
const { children, data } = $props();

const large = new MediaQuery('min-width: 800px');
    const hasNoDetailSelected = $derived.by(() => {
        return (
            typeof $page.state.id === 'undefined' && typeof $page.state.title === 'undefined'
        );
    });

  function onClickItem() {
    pushState('/news/abcdabcd-abcd-abcd-abcd-abcdabcdabcd/title-1', {id: 'abcdabcd-abcd-abcd-abcd-abcdabcdabcd', title: 'title-1'})
  }

</script>

    <header class="header">
        <h1>
            <a data-sveltekit-preload-data="off" href="/">TestNewsApp</a>
        </h1>
    </header>

{#if large.current}
<main style="flex-direction: row">
  <div class="news-list-container">
    <nav>
    <ul>
      <li onclick={onClickItem}>Item 1</li>
    </ul>
    </nav>
  </div>
  <div class="news-detail-container">
    {@render children()}
  </div>
</main>
{:else if !large.current && hasNoDetailSelected}
<main style="flex-direction: column">
  <div class="news-list-container">
    <nav>
    <ul>
      <li onclick={onClickItem}>Item 1</li>
    </ul>
    </nav>
  </div>
</main>
{:else}
<main style="flex-direction: column">
<div class="news-detail-container">
  {@render children()}
</div>
</main>

{/if}

<style>
.news-detail-container {
  background-color: lightyellow;
  flex: 1;
}
.news-list-container {
  background-color: lightcyan;
  flex: 1;
}
main {
  display: flex;
  flex: 1;
}
</style>

src/routes/(news)/+page.svelte

<script lang='ts'>
import {page} from '$app/stores';
</script>

{#if $page.state.id && $page.state.title}
<p>Detail Page</p>
{:else}
<p>Popular News</p>
{/if}

问题

  • 如何让直接输入URL时该功能正常工作?

解决方案

问题核心是:你用pushState修改了客户端URL,但服务器端没有匹配该路径的路由,直接访问时就会返回404。需要让服务器识别这些动态路径,同时调整页面逻辑不再依赖客户端临时状态。

  1. 创建动态路由文件
    在src/routes/(news)/目录下新建[id]/[title]/+page.svelte,用来匹配/news/{id}/{title}格式的路径:
<script lang='ts'>
    // 从URL参数中直接获取id和title
    export let params;
</script>

{#if params.id && params.title}
    <p>Detail Page - ID: {params.id}, Title: {params.title}</p>
{:else}
    <p>Popular News</p>
{/if}
  1. 统一Layout的判断逻辑
    把hasNoDetailSelected的判断从依赖page.state改成依赖URL参数,确保客户端跳转和直接访问的逻辑一致:
const hasNoDetailSelected = $derived.by(() => {
    return typeof $page.params.id === 'undefined' && typeof $page.params.title === 'undefined';
});
  1. 可选:优化客户端跳转
    如果要保持客户端跳转的流畅性,可以把pushState换成goto,路径保持不变即可,新路由已经能匹配该路径:
import { goto } from '$app/navigation';

// 替换原来的pushState调用
function onClickItem() {
    goto('/news/abcdabcd-abcd-abcd-abcd-abcdabcdabcd/title-1');
}

修改完成后,无论点击项目跳转还是直接输入URL访问,都能正常加载详情页,不会再出现404。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 10:10:07