首页 / Svelte 5 入门教程 / 高级路由与布局

Svelte 5 入门教程

高级路由与布局

本教程共 50 篇 · 第 45 篇 · 更新于 2026-08-05 · 约 6 分钟阅读

SvelteSvelteKit高级路由布局匹配器

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 按以下规则排序:

  1. 无参数路由优先级最高(foo-abc > [b]
  2. 带匹配器的参数优先于普通参数([a=x] > [a]
  3. 可选参数和 REST 参数优先级最低
  4. 同级按字母排序

比如这些路由都能匹配 /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() 做服务端重定向