高级路由与布局
本教程共 50 篇 · 第 45 篇 · 更新于 2026-08-05 · 约 6 分钟阅读
45. 高级路由与布局
本节目标:掌握 SvelteKit 的高级路由功能,包括 REST 参数、可选参数、匹配器、路由组和布局重置。
REST 参数
动态路由 [slug] 只匹配一个路径段。如果路径段数量不确定,用 REST 参数 [...file]:
src/routes/[org]/[repo]/tree/[branch]/[...file]
访问 /sveltejs/kit/tree/main/docs/readme.md 时,参数为:
{
org: 'sveltejs',
repo: 'kit',
branch: 'main',
file: 'docs/readme.md' // 匹配剩余所有路径段
}
Note
[...rest]可以匹配零个路径段。比如src/routes/a/[...rest]/z/+page.svelte能匹配/a/z(rest 为空)、/a/b/z、/a/b/c/z。
自定义 404 页面
默认情况下,未匹配路由的请求返回全局 404。如果想在某个区域内自定义 404,加一个 [...path] 路由:
src/routes/
├ marx-brothers/
│ ├── [...path]/
│ ├── chico/
│ ├── harpo/
│ └ +error.svelte
└ +error.svelte
// src/routes/marx-brothers/[...path]/+page.js
import { error } from '@sveltejs/kit';
/** @type {import('./$types').PageLoad} */
export function load() {
error(404, 'Not Found');
}
访问 /marx-brothers/karl 时,[...path] 匹配并返回 404,触发 marx-brothers/+error.svelte。
可选参数
用双括号 [[lang]] 创建可选参数。[[lang]]/home 同时匹配 /home 和 /en/home:
src/routes/[[lang]]/home/+page.svelte
// /home → params.lang 为 undefined
// /en/home → params.lang 为 'en'
// /zh/home → params.lang 为 'zh'
Note可选参数不能跟在 REST 参数后面。
[...rest]/[[optional]]中 optional 永远不会被使用,因为 rest 会贪婪地匹配所有路径。
匹配器
[slug] 会匹配任何值,包括不合法的。比如 /fruits/apple 和 /fruits/rocketship 都能匹配 src/routes/fruits/[page]。
用匹配器限制参数格式。在 src/params/ 目录下创建匹配器:
// src/params/fruit.js
/** @type {import('@sveltejs/kit').ParamMatcher} */
export function match(param) {
return param === 'apple' || param === 'orange';
}
在路由中使用 [page=fruit] 语法指定匹配器:
src/routes/fruits/[page=fruit]/+page.svelte
现在 /fruits/apple 匹配成功,/fruits/rocketship 不匹配,SvelteKit 会继续尝试其他路由,最终返回 404。
Tip匹配器在服务端和浏览器端都会运行。
src/params/下的*.test.js和*.spec.js文件会被当作测试文件,不当作匹配器。
路由排序
多个路由可能匹配同一个路径。SvelteKit 按以下规则排序:
- 无参数路由优先级最高(
foo-abc>[b]) - 带匹配器的参数优先于普通参数(
[a=x]>[a]) - 可选参数和 REST 参数优先级最低
- 同级按字母排序
比如这些路由都能匹配 /foo-abc,排序后优先级从高到低:
src/routes/foo-abc/+page.svelte # 精确匹配,最高
src/routes/foo-[c]/+page.svelte # 带动态参数
src/routes/[[a=x]]/+page.svelte # 可选参数带匹配器
src/routes/[b]/+page.svelte # 普通动态参数
src/routes/[...catchall]/+page.svelte # REST 参数,最低
路由组 (group)
用括号包裹的目录名不影响 URL 路径,但可以组织布局。比如应用页面和营销页面需要不同的布局:
src/routes/
├ (app)/
│ ├ dashboard/
│ ├ item/
│ └ +layout.svelte # 应用布局(导航栏 + 侧边栏)
├ (marketing)/
│ ├ about/
│ ├ testimonials/
│ └ +layout.svelte # 营销布局(顶部大图 + CTA)
├ admin/
└ +layout.svelte # 根布局
(app) 和 (marketing) 不出现在 URL 中。/dashboard 使用 (app)/+layout.svelte,/about 使用 (marketing)/+layout.svelte。
Note
(app)下的页面继承根布局和(app)布局。/admin不在任何组里,只继承根布局。
也可以直接在组里放 +page.svelte,比如让首页属于某个组:
src/routes/
├ (app)/
│ ├ +page.svelte # 首页 /,使用 (app) 布局
│ ├ dashboard/
│ └ +layout.svelte
布局重置
有时候某个页面需要跳过中间的布局层级。用 @ 语法重置布局:
src/routes/
├ (app)/
│ ├ item/
│ │ ├ [id]/
│ │ │ ├ embed/
│ │ │ │ └ +page@(app).svelte # 跳过 item 和 [id] 布局,从 (app) 布局开始
│ │ │ └ +layout.svelte
│ │ └ +layout.svelte
│ └ +layout.svelte
└ +layout.svelte
@ 后面跟要重置到的布局层级名:
| 文件名 | 继承的布局 |
|---|---|
+page@[id].svelte | 从 (app)/item/[id]/+layout.svelte 开始 |
+page@item.svelte | 从 (app)/item/+layout.svelte 开始 |
+page@(app).svelte | 从 (app)/+layout.svelte 开始 |
+page@.svelte | 从根 +layout.svelte 开始 |
Tip嵌入页面(embed)常用布局重置。embed 页面通常不需要导航栏和侧边栏,用
+page@.svelte直接回到根布局。
布局自身重置
布局组件也可以用 @ 重置自己的父布局。比如某个区域的布局想跳过上级布局:
src/routes/
├ (app)/
│ ├ item/
│ │ ├ [id]/
│ │ │ ├ +layout.svelte # 正常继承
│ │ │ └ +page.svelte
│ │ └ +layout@.svelte # 跳过 (app) 布局,直接从根布局继承
│ └ +layout.svelte
└ +layout.svelte
+layout@.svelte 让 /item/[id]/ 下的所有页面跳过 (app)/+layout.svelte,直接继承根布局。
特殊字符编码
文件名中有些字符不能直接用(如 /、:、?)。用十六进制转义 [x+nn]:
| 字符 | 编码 |
|---|---|
/ | [x+2f] |
: | [x+3a] |
? | [x+3f] |
# | [x+23] |
[ | [x+5b] |
] | [x+5d] |
比如创建 /smileys/:-) 路由:
src/routes/smileys/[x+3a]-[x+29]/+page.svelte
Unicode 字符也可以直接用或用 [u+nnnn] 转义:
src/routes/🤪/+page.svelte
# 等价于
src/routes/[u+d83e][u+dd2a]/+page.svelte
页面重定向
在 load 函数中用 redirect 跳转:
// src/routes/old/+page.server.js
import { redirect } from '@sveltejs/kit';
/** @type {import('./$types').PageServerLoad} */
export function load() {
redirect(308, '/new');
}
状态码通常用 301(永久)或 307(临时)。load 函数中的重定向对用户是透明的。
本节回顾
[...file]匹配多个路径段,[[lang]]是可选参数- 匹配器在
src/params/中定义,用[param=matcher]指定 - 路由排序:精确匹配 > 带匹配器参数 > 普通参数 > 可选/REST 参数
(group)目录不影响 URL,用于组织不同布局+page@.svelte重置布局层级,@后面指定从哪个布局开始- 布局自身也可以重置:
+layout@.svelte - 特殊字符用
[x+nn]十六进制编码 load函数中用redirect()做服务端重定向