如何在SvelteKit中用单个+page.svelte实现Nuxt 2路由结构
在SvelteKit v5中用单个+page.svelte实现Nuxt 2风格的新闻列表/详情路由布局
1. 搭建核心路由结构
我们只需要一个动态路由文件就能覆盖所有目标路由场景,同时配置路由别名映射根路径:
- 创建文件:
src/routes/news/[tag]?/+page.svelte([tag]?表示tag参数可选) - 在
svelte.config.js中配置根路径别名,让/直接映射到/news:
import { sveltekit } from '@sveltejs/kit/vite'; import { defineConfig } from 'vite'; export default defineConfig({ plugins: [sveltekit()], kit: { routes: { alias: { '/': '/news' } } } });
2. 页面内逻辑处理
在+page.svelte中获取路由参数、查询参数,判断视图状态并渲染对应组件:
<script> import { page } from '$app/stores'; import NewsListWrapper from '$lib/components/NewsListWrapper.svelte'; import NewsDetailWrapper from '$lib/components/NewsDetailWrapper.svelte'; // 响应式判断是否为详情视图(存在合法的id和title参数) $: isDetailView = $page.params.id && $page.params.title; // 获取搜索、过滤查询参数 $: filter = $page.url.searchParams.get('filter'); $: searchTerm = $page.url.searchParams.get('search'); // 响应式判断设备类型 $: isMobile = typeof window !== 'undefined' ? window.innerWidth < 768 : false; </script> <!-- 桌面端布局:始终显示列表,详情页叠加详情组件 --> <div class="desktop-layout"> <NewsListWrapper tag={$page.params.tag} filter={filter} search={searchTerm} /> {#if isDetailView} <NewsDetailWrapper tag={$page.params.tag} id={$page.params.id} title={$page.params.title} /> {/if} </div> <!-- 移动端布局:列表页只显示列表,详情页只显示详情 --> <div class="mobile-layout"> {#if isDetailView} <NewsDetailWrapper tag={$page.params.tag} id={$page.params.id} title={$page.params.title} /> {:else} <NewsListWrapper tag={$page.params.tag} filter={filter} search={searchTerm} /> {/if} </div> <style> .desktop-layout { display: grid; grid-template-columns: 300px 1fr; gap: 2rem; } .mobile-layout { width: 100%; } @media (max-width: 767px) { .desktop-layout { display: none; } } @media (min-width: 768px) { .mobile-layout { display: none; } } </style>
3. 验证UUID格式的ID参数
在src/routes/news/[tag]?/+page.server.js中添加参数校验,确保id符合UUID格式,不符合则返回404:
export async function load({ params }) { const uuidRegex = /^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$/; if (params.id && !uuidRegex.test(params.id)) { throw new Error('Not found'); } return { tag: params.tag, id: params.id, title: params.title }; }
最终效果
- 列表类路由(
/、/news、/news/:tag及带查询参数的变体):桌面端显示列表+空白详情区域,移动端仅显示列表 - 详情类路由(
/news/:id/:title、/news/:tag/:id/:title):桌面端显示列表+详情,移动端仅显示详情 - 所有路由逻辑集中在单个
+page.svelte文件中,与Nuxt 2的实现逻辑完全对齐
内容的提问来源于stack exchange,提问作者PirateApp
相关产品推荐
相关产品推荐

