直接输入URL或重载时Shallow Routing报404的解决方法
问题现象
点击项目时Shallow Routing工作正常

直接输入项目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。需要让服务器识别这些动态路径,同时调整页面逻辑不再依赖客户端临时状态。
- 创建动态路由文件
在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}
- 统一Layout的判断逻辑
把hasNoDetailSelected的判断从依赖page.state改成依赖URL参数,确保客户端跳转和直接访问的逻辑一致:
const hasNoDetailSelected = $derived.by(() => { return typeof $page.params.id === 'undefined' && typeof $page.params.title === 'undefined'; });
- 可选:优化客户端跳转
如果要保持客户端跳转的流畅性,可以把pushState换成goto,路径保持不变即可,新路由已经能匹配该路径:
import { goto } from '$app/navigation'; // 替换原来的pushState调用 function onClickItem() { goto('/news/abcdabcd-abcd-abcd-abcd-abcdabcdabcd/title-1'); }
修改完成后,无论点击项目跳转还是直接输入URL访问,都能正常加载详情页,不会再出现404。
内容的提问来源于stack exchange,提问作者PirateApp
相关产品推荐
相关产品推荐

