Skip to main content

Routing

SvelteKit 的核心是一个基于文件系统的路由器*。您的应用程序的路由——即用户可以访问的 URL 路径——由代码库中的目录定义:*

  • src/routes 是根路由
  • src/routes/about 创建了一个 /about 路由
  • src/routes/blog/[slug] 创建了一个带有 参数 的路由,slug,可以在用户请求类似 /blog/hello-world 的页面时动态加载数据

[!注意] 您可以通过编辑 项目配置src/routes 改为不同的目录。

每个路由目录包含一个或多个路由文件,可以通过它们的+前缀来识别。

我们将稍后更详细地介绍这些文件,但这里有一些简单的规则可以帮助您记住 SvelteKit 的路由工作方式:

  • 所有文件都可以在服务器上运行
  • 所有文件都在客户端运行,除了+服务器文件
  • +layout+error 文件同样适用于子目录以及它们所在的目录

+页面

+page.svelte

一个 +page.svelte 组件定义了您的应用页面。默认情况下,页面在服务器(SSR)上对初始请求进行渲染,并在浏览器(CSR)上对后续导航进行渲染。

src/routes/+page
<h1>Hello and welcome to my site!</h1>
<a href="/about">About my site</a>
src/routes/about/+page
<h1>About this site</h1>
<p>TODO...</p>
<a href="/">Home</a>

[注意] SvelteKit 使用<a>元素在路由之间导航,而不是框架特定的<Link>组件。

页面可以通过load函数通过data属性接收数据。

src/routes/blog/[slug]/+page
<script>
	/** @type {import('./$types').PageProps} */
	let { data } = $props();
</script>

<h1>{data.title}</h1>
<div>{@html data.content}</div>
<script lang="ts">
	import type { PageProps } from './$types';

	let { data }: PageProps = $props();
</script>

<h1>{data.title}</h1>
<div>{@html data.content}</div>

[!旧版] PageProps 在 2.16.0 版本中添加。在早期版本中,您必须手动输入 data 属性,使用 PageData 代替,参见 [类型](#\types)。

在 Svelte 4 中,您将使用 export let data 代替。

+page.js

通常,页面在渲染之前需要加载一些数据。为此,我们添加了一个 +page.js 模块,该模块导出了一个 load 函数:

src/routes/blog/[slug]/+page
import { function error(status: number, body: App.Error): never (+1 overload)

Throws an error with a HTTP status code and an optional message. When called during request handling, this will cause SvelteKit to return an error response without invoking handleError. Make sure you’re not catching the thrown error, which would prevent SvelteKit from handling it.

@paramstatus The HTTP status code. Must be in the range 400-599.
@parambody An object that conforms to the App.Error type. If a string is passed, it will be used as the message property.
@throwsHttpError This error instructs SvelteKit to initiate HTTP error handling.
@throwsError If the provided status is invalid (not between 400 and 599).
error
} from '@sveltejs/kit';
/** @type {import('./$types').PageLoad} */ export function
function load({ params }: {
    params: any;
}): {
    title: string;
    content: string;
}
@type{import('./$types').PageLoad}
load
({ params: anyparams }) {
if (params: anyparams.slug === 'hello-world') { return { title: stringtitle: 'Hello world!', content: stringcontent: 'Welcome to our blog. Lorem ipsum dolor sit amet...' }; }
function error(status: number, body?: {
    message: string;
} extends App.Error ? App.Error | string | undefined : never): never (+1 overload)

Throws an error with a HTTP status code and an optional message. When called during request handling, this will cause SvelteKit to return an error response without invoking handleError. Make sure you’re not catching the thrown error, which would prevent SvelteKit from handling it.

@paramstatus The HTTP status code. Must be in the range 400-599.
@parambody An object that conforms to the App.Error type. If a string is passed, it will be used as the message property.
@throwsHttpError This error instructs SvelteKit to initiate HTTP error handling.
@throwsError If the provided status is invalid (not between 400 and 599).
error
(404, 'Not found');
}
import { function error(status: number, body: App.Error): never (+1 overload)

Throws an error with a HTTP status code and an optional message. When called during request handling, this will cause SvelteKit to return an error response without invoking handleError. Make sure you’re not catching the thrown error, which would prevent SvelteKit from handling it.

@paramstatus The HTTP status code. Must be in the range 400-599.
@parambody An object that conforms to the App.Error type. If a string is passed, it will be used as the message property.
@throwsHttpError This error instructs SvelteKit to initiate HTTP error handling.
@throwsError If the provided status is invalid (not between 400 and 599).
error
} from '@sveltejs/kit';
import type {
type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
PageLoad
} from './$types';
export const const load: PageLoadload:
type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
PageLoad
= ({ params: Record<string, any>

The parameters of the current page - e.g. for a route like /blog/[slug], a { slug: string } object

params
}) => {
if (params: Record<string, any>

The parameters of the current page - e.g. for a route like /blog/[slug], a { slug: string } object

params
.slug === 'hello-world') {
return { title: stringtitle: 'Hello world!', content: stringcontent: 'Welcome to our blog. Lorem ipsum dolor sit amet...' }; }
function error(status: number, body?: {
    message: string;
} extends App.Error ? App.Error | string | undefined : never): never (+1 overload)

Throws an error with a HTTP status code and an optional message. When called during request handling, this will cause SvelteKit to return an error response without invoking handleError. Make sure you’re not catching the thrown error, which would prevent SvelteKit from handling it.

@paramstatus The HTTP status code. Must be in the range 400-599.
@parambody An object that conforms to the App.Error type. If a string is passed, it will be used as the message property.
@throwsHttpError This error instructs SvelteKit to initiate HTTP error handling.
@throwsError If the provided status is invalid (not between 400 and 599).
error
(404, 'Not found');
};

此函数与+page.svelte并行运行,这意味着它在服务器端渲染期间在服务器上运行,在客户端导航期间在浏览器中运行。有关 API 的完整详细信息,请参阅load

除了load+page.js还可以导出配置页面行为的值:

  • export const prerender = truefalse'auto'
  • export const ssr = truefalse
  • export const csr = truefalse

您可以在页面选项中找到更多关于这些信息。

+page.server.js

如果您的load函数只能在服务器上运行——例如,如果它需要从数据库获取数据或您需要访问像 API 密钥这样的私有环境变量——那么您可以重命名+page.js+page.server.js并将PageLoad类型更改为PageServerLoad

src/routes/blog/[slug]/+page.server
import { function error(status: number, body: App.Error): never (+1 overload)

Throws an error with a HTTP status code and an optional message. When called during request handling, this will cause SvelteKit to return an error response without invoking handleError. Make sure you’re not catching the thrown error, which would prevent SvelteKit from handling it.

@paramstatus The HTTP status code. Must be in the range 400-599.
@parambody An object that conforms to the App.Error type. If a string is passed, it will be used as the message property.
@throwsHttpError This error instructs SvelteKit to initiate HTTP error handling.
@throwsError If the provided status is invalid (not between 400 and 599).
error
} from '@sveltejs/kit';
/** @type {import('./$types').PageServerLoad} */ export async function function load(event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').PageServerLoad}
load
({ params: Record<string, any>

The parameters of the current route - e.g. for a route like /blog/[slug], a { slug: string } object.

params
}) {
const
const post: {
    title: string;
    content: string;
}
post
= await
const getPostFromDatabase: (slug: string) => {
    title: string;
    content: string;
}
getPostFromDatabase
(params: Record<string, any>

The parameters of the current route - e.g. for a route like /blog/[slug], a { slug: string } object.

params
.slug);
if (
const post: {
    title: string;
    content: string;
}
post
) {
return
const post: {
    title: string;
    content: string;
}
post
;
}
function error(status: number, body?: {
    message: string;
} extends App.Error ? App.Error | string | undefined : never): never (+1 overload)

Throws an error with a HTTP status code and an optional message. When called during request handling, this will cause SvelteKit to return an error response without invoking handleError. Make sure you’re not catching the thrown error, which would prevent SvelteKit from handling it.

@paramstatus The HTTP status code. Must be in the range 400-599.
@parambody An object that conforms to the App.Error type. If a string is passed, it will be used as the message property.
@throwsHttpError This error instructs SvelteKit to initiate HTTP error handling.
@throwsError If the provided status is invalid (not between 400 and 599).
error
(404, 'Not found');
}
import { function error(status: number, body: App.Error): never (+1 overload)

Throws an error with a HTTP status code and an optional message. When called during request handling, this will cause SvelteKit to return an error response without invoking handleError. Make sure you’re not catching the thrown error, which would prevent SvelteKit from handling it.

@paramstatus The HTTP status code. Must be in the range 400-599.
@parambody An object that conforms to the App.Error type. If a string is passed, it will be used as the message property.
@throwsHttpError This error instructs SvelteKit to initiate HTTP error handling.
@throwsError If the provided status is invalid (not between 400 and 599).
error
} from '@sveltejs/kit';
import type { type PageServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageServerLoad } from './$types'; export const const load: PageServerLoadload: type PageServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageServerLoad = async ({ params: Record<string, any>

The parameters of the current route - e.g. for a route like /blog/[slug], a { slug: string } object.

params
}) => {
const
const post: {
    title: string;
    content: string;
}
post
= await
const getPostFromDatabase: (slug: string) => {
    title: string;
    content: string;
}
getPostFromDatabase
(params: Record<string, any>

The parameters of the current route - e.g. for a route like /blog/[slug], a { slug: string } object.

params
.slug);
if (
const post: {
    title: string;
    content: string;
}
post
) {
return
const post: {
    title: string;
    content: string;
}
post
;
}
function error(status: number, body?: {
    message: string;
} extends App.Error ? App.Error | string | undefined : never): never (+1 overload)

Throws an error with a HTTP status code and an optional message. When called during request handling, this will cause SvelteKit to return an error response without invoking handleError. Make sure you’re not catching the thrown error, which would prevent SvelteKit from handling it.

@paramstatus The HTTP status code. Must be in the range 400-599.
@parambody An object that conforms to the App.Error type. If a string is passed, it will be used as the message property.
@throwsHttpError This error instructs SvelteKit to initiate HTTP error handling.
@throwsError If the provided status is invalid (not between 400 and 599).
error
(404, 'Not found');
};

在客户端导航期间,SvelteKit 将从服务器加载此数据,这意味着返回的值必须使用devalue进行序列化。请参阅load以获取 API 的完整详细信息。

+page.js类似,+page.server.js可以导出页面选项——预渲染服务器端渲染客户端渲染

一个 +page.server.js 文件也可以导出 actions。如果 load 允许您从服务器读取数据,actions 则允许您使用 <form> 元素将数据 写入 服务器。要了解如何使用它们,请参阅 表单操作 部分。

+错误

如果加载过程中发生错误,SvelteKit 将渲染默认错误页面。您可以通过添加一个+error.svelte文件来根据每个路由自定义此错误页面:

src/routes/blog/[slug]/+error
<script>
	import { page } from '$app/state';
</script>

<h1>{page.status}: {page.error.message}</h1>
<script lang="ts">
	import { page } from '$app/state';
</script>

<h1>{page.status}: {page.error.message}</h1>

[!旧版] $app/state 在 SvelteKit 2.12 中被添加。如果您使用的是更早的版本或使用 Svelte 4,请使用 $app/stores 代替。

SvelteKit 将“遍历树形结构”以寻找最近的错误边界——如果上面的文件不存在,它将尝试src/routes/blog/+error.svelte,然后是src/routes/+error.svelte,在渲染默认错误页面之前。如果失败了(或者如果错误是从根load函数中抛出的,该函数位于根+layout之上,而+error位于其“上方”),SvelteKit 将退出并渲染一个静态的回退错误页面,您可以通过创建一个src/error.html文件来自定义它。

如果错误发生在 load 函数内部,在 +layout(.server).js 中,树中最接近的错误边界是一个位于布局 上方+error.svelte 文件(而不是紧挨着它)。

如果找不到路由(404),将使用src/routes/+error.svelte(或默认错误页面,如果该文件不存在)。

[!注意] +error.sveltehandle+server.js 请求处理器内部发生错误时 被使用。

您可以在这里了解更多关于错误处理的信息。

+布局

截至目前,我们将页面视为完全独立的组件——在导航时,现有的+page.svelte组件将被销毁,并由新的一个取代。

但许多应用中,有一些元素应该在每一页都可见,例如顶级导航或页脚。我们不必在每一页的+page.svelte中重复它们,而是可以将它们放在布局中。

+layout.svelte

为创建适用于所有页面的布局,创建一个名为 src/routes/+layout.svelte 的文件。默认布局(SvelteKit 在没有提供自己的布局时使用的布局)看起来像这样...

<script>
	let { children } = $props();
</script>

{@render children()}

...但我们可以添加任何标记、样式和行为。唯一的要求是组件必须包含一个用于页面内容的@render标签。例如,让我们添加一个导航栏:

src/routes/+layout
<script>
	let { children } = $props();
</script>

<nav>
	<a href="/">Home</a>
	<a href="/about">About</a>
	<a href="/settings">Settings</a>
</nav>

{@render children()}
<script lang="ts">
	let { children } = $props();
</script>

<nav>
	<a href="/">Home</a>
	<a href="/about">About</a>
	<a href="/settings">Settings</a>
</nav>

{@render children()}

如果我们为//about/settings创建页面...

src/routes/+page
<h1>Home</h1>
src/routes/about/+page
<h1>About</h1>
src/routes/settings/+page
<h1>Settings</h1>

...导航将始终可见,在三个页面之间点击只会导致 <h1> 被替换。

布局可以是嵌套的。假设我们不仅仅有一个单独的 /settings 页面,而是有嵌套页面,如 /settings/profile/settings/notifications,它们共享一个子菜单(以现实生活中的例子,见 github.com/settings)。

我们可以创建一个仅适用于页面下方 /settings 的布局(同时继承顶级导航的根布局):

src/routes/settings/+layout
<script>
	/** @type {import('./$types').LayoutProps} */
	let { data, children } = $props();
</script>

<h1>Settings</h1>

<div class="submenu">
	{#each data.sections as section}
		<a href="/settings/{section.slug}">{section.title}</a>
	{/each}
</div>

{@render children()}
<script lang="ts">
	import type { LayoutProps } from './$types';

	let { data, children }: LayoutProps = $props();
</script>

<h1>Settings</h1>

<div class="submenu">
	{#each data.sections as section}
		<a href="/settings/{section.slug}">{section.title}</a>
	{/each}
</div>

{@render children()}

[!旧版] LayoutProps 在 2.16.0 版本中添加。在早期版本中,您必须 手动输入属性

您可以通过查看下一节中位于下面的+layout.js示例来了解数据是如何填充的。

默认情况下,每个布局都继承其上方的布局。有时这并不是你想要的 - 在这种情况下,高级布局可以帮助你。

+layout.js

就像 +page.svelte+page.js 加载数据一样,你的 +layout.svelte 组件可以从 +layout.js 中的 load 函数获取数据。

src/routes/settings/+layout
/** @type {import('./$types').LayoutLoad} */
export function 
function load(): {
    sections: {
        slug: string;
        title: string;
    }[];
}
@type{import('./$types').LayoutLoad}
load
() {
return {
sections: {
    slug: string;
    title: string;
}[]
sections
: [
{ slug: stringslug: 'profile', title: stringtitle: 'Profile' }, { slug: stringslug: 'notifications', title: stringtitle: 'Notifications' } ] }; }
import type { 
type LayoutLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
type LayoutLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
LayoutLoad
} from './$types';
export const const load: LayoutLoadload:
type LayoutLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
type LayoutLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
LayoutLoad
= () => {
return {
sections: {
    slug: string;
    title: string;
}[]
sections
: [
{ slug: stringslug: 'profile', title: stringtitle: 'Profile' }, { slug: stringslug: 'notifications', title: stringtitle: 'Notifications' } ] }; };

如果 +layout.js 导出 页面选项 —— 预渲染SSRCSR —— 它们将被用作子页面的默认值。

数据从布局的 加载 函数返回,也对其所有子页面可用:

src/routes/settings/profile/+page
<script>
	/** @type {import('./$types').PageProps} */
	let { data } = $props();

	console.log(data.sections); // [{ slug: 'profile', title: 'Profile' }, ...]
</script>
<script lang="ts">
	import type { PageProps } from './$types';

	let { data }: PageProps = $props();

	console.log(data.sections); // [{ slug: 'profile', title: 'Profile' }, ...]
</script>

[注意] 在页面间导航时,布局数据通常保持不变。SvelteKit 将在必要时智能地重新运行加载函数。

+layout.server.js

要在服务器上运行您布局的load函数,请将其移动到+layout.server.js,并将LayoutLoad类型更改为LayoutServerLoad

+layout.js类似,+layout.server.js可以导出页面选项——预渲染服务器端渲染客户端渲染

+服务器

以及页面,您还可以使用+server.js文件(有时称为“API 路由”或“端点”)来定义路由,该文件让您完全控制响应。您的+server.js文件导出与 HTTP 动词(如GETPOSTPATCHPUTDELETEOPTIONSHEAD)对应的函数,这些函数接受一个RequestEvent参数并返回一个Response对象。

例如,我们可以创建一个 /api/random-number 路由,并使用一个 GET 处理器:

src/routes/api/random-number/+server
import { function error(status: number, body: App.Error): never (+1 overload)

Throws an error with a HTTP status code and an optional message. When called during request handling, this will cause SvelteKit to return an error response without invoking handleError. Make sure you’re not catching the thrown error, which would prevent SvelteKit from handling it.

@paramstatus The HTTP status code. Must be in the range 400-599.
@parambody An object that conforms to the App.Error type. If a string is passed, it will be used as the message property.
@throwsHttpError This error instructs SvelteKit to initiate HTTP error handling.
@throwsError If the provided status is invalid (not between 400 and 599).
error
} from '@sveltejs/kit';
/** @type {import('./$types').RequestHandler} */ export function
function GET({ url }: {
    url: any;
}): Response
@type{import('./$types').RequestHandler}
GET
({ url: anyurl }) {
const const min: numbermin =
var Number: NumberConstructor
(value?: any) => number

An object that represents a number of any kind. All JavaScript numbers are 64-bit floating-point numbers.

Number
(url: anyurl.searchParams.get('min') ?? '0');
const const max: numbermax =
var Number: NumberConstructor
(value?: any) => number

An object that represents a number of any kind. All JavaScript numbers are 64-bit floating-point numbers.

Number
(url: anyurl.searchParams.get('max') ?? '1');
const const d: numberd = const max: numbermax - const min: numbermin; if (function isNaN(number: number): boolean

Returns a Boolean value that indicates whether a value is the reserved value NaN (not a number).

@paramnumber A numeric value.
isNaN
(const d: numberd) || const d: numberd < 0) {
function error(status: number, body?: {
    message: string;
} extends App.Error ? App.Error | string | undefined : never): never (+1 overload)

Throws an error with a HTTP status code and an optional message. When called during request handling, this will cause SvelteKit to return an error response without invoking handleError. Make sure you’re not catching the thrown error, which would prevent SvelteKit from handling it.

@paramstatus The HTTP status code. Must be in the range 400-599.
@parambody An object that conforms to the App.Error type. If a string is passed, it will be used as the message property.
@throwsHttpError This error instructs SvelteKit to initiate HTTP error handling.
@throwsError If the provided status is invalid (not between 400 and 599).
error
(400, 'min and max must be numbers, and min must be less than max');
} const const random: numberrandom = const min: numbermin + var Math: Math

An intrinsic object that provides basic mathematics functionality and constants.

Math
.Math.random(): number

Returns a pseudorandom number between 0 and 1.

random
() * const d: numberd;
return new var Response: new (body?: BodyInit | null, init?: ResponseInit) => Response

This Fetch API interface represents the response to a request.

MDN Reference

Response
(
var String: StringConstructor
(value?: any) => string

Allows manipulation and formatting of text strings and determination and location of substrings within strings.

String
(const random: numberrandom));
}
import { function error(status: number, body: App.Error): never (+1 overload)

Throws an error with a HTTP status code and an optional message. When called during request handling, this will cause SvelteKit to return an error response without invoking handleError. Make sure you’re not catching the thrown error, which would prevent SvelteKit from handling it.

@paramstatus The HTTP status code. Must be in the range 400-599.
@parambody An object that conforms to the App.Error type. If a string is passed, it will be used as the message property.
@throwsHttpError This error instructs SvelteKit to initiate HTTP error handling.
@throwsError If the provided status is invalid (not between 400 and 599).
error
} from '@sveltejs/kit';
import type {
type RequestHandler = (event: Kit.RequestEvent<Record<string, any>, string | null>) => MaybePromise<Response>
type RequestHandler = (event: Kit.RequestEvent<Record<string, any>, string | null>) => MaybePromise<Response>
RequestHandler
} from './$types';
export const const GET: RequestHandlerGET:
type RequestHandler = (event: Kit.RequestEvent<Record<string, any>, string | null>) => MaybePromise<Response>
type RequestHandler = (event: Kit.RequestEvent<Record<string, any>, string | null>) => MaybePromise<Response>
RequestHandler
= ({ url: URL

The requested URL.

url
}) => {
const const min: numbermin =
var Number: NumberConstructor
(value?: any) => number

An object that represents a number of any kind. All JavaScript numbers are 64-bit floating-point numbers.

Number
(url: URL

The requested URL.

url
.URL.searchParams: URLSearchParamssearchParams.URLSearchParams.get(name: string): string | null

Returns the first value associated to the given search parameter.

MDN Reference

get
('min') ?? '0');
const const max: numbermax =
var Number: NumberConstructor
(value?: any) => number

An object that represents a number of any kind. All JavaScript numbers are 64-bit floating-point numbers.

Number
(url: URL

The requested URL.

url
.URL.searchParams: URLSearchParamssearchParams.URLSearchParams.get(name: string): string | null

Returns the first value associated to the given search parameter.

MDN Reference

get
('max') ?? '1');
const const d: numberd = const max: numbermax - const min: numbermin; if (function isNaN(number: number): boolean

Returns a Boolean value that indicates whether a value is the reserved value NaN (not a number).

@paramnumber A numeric value.
isNaN
(const d: numberd) || const d: numberd < 0) {
function error(status: number, body?: {
    message: string;
} extends App.Error ? App.Error | string | undefined : never): never (+1 overload)

Throws an error with a HTTP status code and an optional message. When called during request handling, this will cause SvelteKit to return an error response without invoking handleError. Make sure you’re not catching the thrown error, which would prevent SvelteKit from handling it.

@paramstatus The HTTP status code. Must be in the range 400-599.
@parambody An object that conforms to the App.Error type. If a string is passed, it will be used as the message property.
@throwsHttpError This error instructs SvelteKit to initiate HTTP error handling.
@throwsError If the provided status is invalid (not between 400 and 599).
error
(400, 'min and max must be numbers, and min must be less than max');
} const const random: numberrandom = const min: numbermin + var Math: Math

An intrinsic object that provides basic mathematics functionality and constants.

Math
.Math.random(): number

Returns a pseudorandom number between 0 and 1.

random
() * const d: numberd;
return new var Response: new (body?: BodyInit | null, init?: ResponseInit) => Response

This Fetch API interface represents the response to a request.

MDN Reference

Response
(
var String: StringConstructor
(value?: any) => string

Allows manipulation and formatting of text strings and determination and location of substrings within strings.

String
(const random: numberrandom));
};

第一个参数可以是ReadableStream,这使得可以流式传输大量数据或创建服务器发送事件(除非部署到像 AWS Lambda 这样的缓冲响应的平台)。

您可以使用来自 @sveltejs/kiterrorredirectjson 方法以提高便利性(但您不必这样做)。

如果抛出错误(无论是 error(...) 还是意外错误),响应将是一个错误或回退错误页面的 JSON 表示形式——可以通过 src/error.html 进行自定义——具体取决于 Accept 头部。在这种情况下,+error.svelte 组件将 不会 被渲染。您可以在 这里 了解更多关于错误处理的信息。

[!注意] 当创建一个 OPTIONS 处理器时,请注意 Vite 将注入 Access-Control-Allow-OriginAccess-Control-Allow-Methods 头部信息——除非您添加它们,否则在生产环境中这些信息将不存在。

[!注意] +layout 文件对 +server.js 文件没有影响。如果您想在每次请求之前运行一些逻辑,请将其添加到服务器的 handle 钩子中。

接收数据

通过导出 POST / PUT/PATCH/DELETE/OPTIONS/HEAD 处理程序,可以使用 +server.js 文件创建完整的 API:

src/routes/add/+page
<script>
	let a = 0;
	let b = 0;
	let total = 0;

	async function add() {
		const response = await fetch('/api/add', {
			method: 'POST',
			body: JSON.stringify({ a, b }),
			headers: {
				'content-type': 'application/json'
			}
		});

		total = await response.json();
	}
</script>

<input type="number" bind:value={a}> +
<input type="number" bind:value={b}> =
{total}

<button onclick={add}>Calculate</button>
<script lang="ts">
	let a = 0;
	let b = 0;
	let total = 0;

	async function add() {
		const response = await fetch('/api/add', {
			method: 'POST',
			body: JSON.stringify({ a, b }),
			headers: {
				'content-type': 'application/json'
			}
		});

		total = await response.json();
	}
</script>

<input type="number" bind:value={a}> +
<input type="number" bind:value={b}> =
{total}

<button onclick={add}>Calculate</button>
src/routes/api/add/+server
import { function json(data: any, init?: ResponseInit | undefined): Response

Create a JSON Response object from the supplied data.

@paramdata The value that will be serialized as JSON.
@paraminit Options such as status and headers that will be added to the response. Content-Type: application/json and Content-Length headers will be added automatically.
json
} from '@sveltejs/kit';
/** @type {import('./$types').RequestHandler} */ export async function
function POST({ request }: {
    request: any;
}): Promise<Response>
@type{import('./$types').RequestHandler}
POST
({ request: anyrequest }) {
const { const a: anya, const b: anyb } = await request: anyrequest.json(); return function json(data: any, init?: ResponseInit | undefined): Response

Create a JSON Response object from the supplied data.

@paramdata The value that will be serialized as JSON.
@paraminit Options such as status and headers that will be added to the response. Content-Type: application/json and Content-Length headers will be added automatically.
json
(const a: anya + const b: anyb);
}
import { function json(data: any, init?: ResponseInit | undefined): Response

Create a JSON Response object from the supplied data.

@paramdata The value that will be serialized as JSON.
@paraminit Options such as status and headers that will be added to the response. Content-Type: application/json and Content-Length headers will be added automatically.
json
} from '@sveltejs/kit';
import type {
type RequestHandler = (event: Kit.RequestEvent<Record<string, any>, string | null>) => MaybePromise<Response>
type RequestHandler = (event: Kit.RequestEvent<Record<string, any>, string | null>) => MaybePromise<Response>
RequestHandler
} from './$types';
export const const POST: RequestHandlerPOST:
type RequestHandler = (event: Kit.RequestEvent<Record<string, any>, string | null>) => MaybePromise<Response>
type RequestHandler = (event: Kit.RequestEvent<Record<string, any>, string | null>) => MaybePromise<Response>
RequestHandler
= async ({ request: Request

The original request object.

request
}) => {
const { const a: anya, const b: anyb } = await request: Request

The original request object.

request
.Body.json(): Promise<any>json();
return function json(data: any, init?: ResponseInit | undefined): Response

Create a JSON Response object from the supplied data.

@paramdata The value that will be serialized as JSON.
@paraminit Options such as status and headers that will be added to the response. Content-Type: application/json and Content-Length headers will be added automatically.
json
(const a: anya + const b: anyb);
};

[!注意] 通常,表单操作是从浏览器向服务器提交数据的一种更好的方式。

[注意] 如果导出 GET 处理器,则 HEAD 请求将返回 content-length,这是 GET 处理器响应体的长度。

回退方法处理器

导出 fallback 处理器将匹配任何未处理的请求方法,包括像 MOVE 这样没有从 +server.js 中专门导出的方法。

src/routes/api/add/+server
import { function json(data: any, init?: ResponseInit | undefined): Response

Create a JSON Response object from the supplied data.

@paramdata The value that will be serialized as JSON.
@paraminit Options such as status and headers that will be added to the response. Content-Type: application/json and Content-Length headers will be added automatically.
json
, function text(body: string, init?: ResponseInit | undefined): Response

Create a Response object from the supplied body.

@parambody The value that will be used as-is.
@paraminit Options such as status and headers that will be added to the response. A Content-Length header will be added automatically.
text
} from '@sveltejs/kit';
/** @type {import('./$types').RequestHandler} */ export async function
function POST({ request }: {
    request: any;
}): Promise<Response>
@type{import('./$types').RequestHandler}
POST
({ request: anyrequest }) {
const { const a: anya, const b: anyb } = await request: anyrequest.json(); return function json(data: any, init?: ResponseInit | undefined): Response

Create a JSON Response object from the supplied data.

@paramdata The value that will be serialized as JSON.
@paraminit Options such as status and headers that will be added to the response. Content-Type: application/json and Content-Length headers will be added automatically.
json
(const a: anya + const b: anyb);
} // This handler will respond to PUT, PATCH, DELETE, etc. /** @type {import('./$types').RequestHandler} */ export async function
function fallback({ request }: {
    request: any;
}): Promise<Response>
@type{import('./$types').RequestHandler}
fallback
({ request: anyrequest }) {
return function text(body: string, init?: ResponseInit | undefined): Response

Create a Response object from the supplied body.

@parambody The value that will be used as-is.
@paraminit Options such as status and headers that will be added to the response. A Content-Length header will be added automatically.
text
(`I caught your ${request: anyrequest.method} request!`);
}
import { function json(data: any, init?: ResponseInit | undefined): Response

Create a JSON Response object from the supplied data.

@paramdata The value that will be serialized as JSON.
@paraminit Options such as status and headers that will be added to the response. Content-Type: application/json and Content-Length headers will be added automatically.
json
, function text(body: string, init?: ResponseInit | undefined): Response

Create a Response object from the supplied body.

@parambody The value that will be used as-is.
@paraminit Options such as status and headers that will be added to the response. A Content-Length header will be added automatically.
text
} from '@sveltejs/kit';
import type {
type RequestHandler = (event: Kit.RequestEvent<Record<string, any>, string | null>) => MaybePromise<Response>
type RequestHandler = (event: Kit.RequestEvent<Record<string, any>, string | null>) => MaybePromise<Response>
RequestHandler
} from './$types';
export const const POST: RequestHandlerPOST:
type RequestHandler = (event: Kit.RequestEvent<Record<string, any>, string | null>) => MaybePromise<Response>
type RequestHandler = (event: Kit.RequestEvent<Record<string, any>, string | null>) => MaybePromise<Response>
RequestHandler
= async ({ request: Request

The original request object.

request
}) => {
const { const a: anya, const b: anyb } = await request: Request

The original request object.

request
.Body.json(): Promise<any>json();
return function json(data: any, init?: ResponseInit | undefined): Response

Create a JSON Response object from the supplied data.

@paramdata The value that will be serialized as JSON.
@paraminit Options such as status and headers that will be added to the response. Content-Type: application/json and Content-Length headers will be added automatically.
json
(const a: anya + const b: anyb);
}; // This handler will respond to PUT, PATCH, DELETE, etc. export const const fallback: RequestHandlerfallback:
type RequestHandler = (event: Kit.RequestEvent<Record<string, any>, string | null>) => MaybePromise<Response>
type RequestHandler = (event: Kit.RequestEvent<Record<string, any>, string | null>) => MaybePromise<Response>
RequestHandler
= async ({ request: Request

The original request object.

request
}) => {
return function text(body: string, init?: ResponseInit | undefined): Response

Create a Response object from the supplied body.

@parambody The value that will be used as-is.
@paraminit Options such as status and headers that will be added to the response. A Content-Length header will be added automatically.
text
(`I caught your ${request: Request

The original request object.

request
.Request.method: string

Returns request’s HTTP method, which is “GET” by default.

MDN Reference

method
} request!`);
};

[!注意] 对于 HEAD 请求,GET 处理器优先于 fallback 处理器。

内容协商

+server.js 文件可以放置在与 +page 文件相同的目录中,允许相同的路由既是页面也是 API 端点。为了确定是哪一个,SvelteKit 应用以下规则:

  • PUT / PATCH/DELETE/OPTIONS 请求始终由 +server.js 处理,因为它们不适用于页面
  • GET / POST/HEAD 请求,如果 accept 头部优先级为 text/html(换句话说,它是一个浏览器页面请求),则被视为页面请求;否则,由 +server.js 处理。
  • 响应 GET 请求将包含一个 Vary: Accept 标头,以便代理和浏览器分别缓存 HTML 和 JSON 响应。

$types

在整个上述示例中,我们一直在从$types.d.ts文件中导入类型。这是一个 SvelteKit 为您在隐藏目录中创建的文件,如果您使用 TypeScript(或带有 JSDoc 类型注解的 JavaScript)进行开发,它会在处理根文件时为您提供类型安全。

例如,将 let { data } = $props() 注释为 PageProps(或 LayoutProps,对于 +layout.svelte 文件)告诉 TypeScript,data 的类型是 load 返回的内容。

src/routes/blog/[slug]/+page
<script>
	/** @type {import('./$types').PageProps} */
	let { data } = $props();
</script>
<script lang="ts">
	import type { PageProps } from './$types';

	let { data }: PageProps = $props();
</script>

[注意] 在 2.16.0 版本中添加的 PagePropsLayoutProps 类型,是输入 data 属性为 PageDataLayoutData 的快捷方式,以及其他属性,例如页面的 form 或布局的 children。在早期版本中,您必须手动输入这些属性。例如,对于一个页面:

+page
/** @type {{ data: import('./$types').PageData, form: import('./$types').ActionData }} */
let { let data: anydata, let form: anyform } = 
function $props(): any
namespace $props

Declares the props that a component accepts. Example:

let { optionalProp = 42, requiredProp, bindableProp = $bindable() }: { optionalProp?: number; requiredProps: string; bindableProp: boolean } = $props();

https://svelte.dev/docs/svelte/$props

$props
();
import type { import PageDataPageData, import ActionDataActionData } from './$types';

let { let data: PageDatadata, let form: ActionDataform }: { data: PageDatadata: import PageDataPageData, form: ActionDataform: import ActionDataActionData } = 
function $props(): any
namespace $props

Declares the props that a component accepts. Example:

let { optionalProp = 42, requiredProp, bindableProp = $bindable() }: { optionalProp?: number; requiredProps: string; bindableProp: boolean } = $props();

https://svelte.dev/docs/svelte/$props

$props
();

或者,对于布局:

+layout
/** @type {{ data: import('./$types').LayoutData, children: Snippet }} */
let { let data: anydata, let children: anychildren } = 
function $props(): any
namespace $props

Declares the props that a component accepts. Example:

let { optionalProp = 42, requiredProp, bindableProp = $bindable() }: { optionalProp?: number; requiredProps: string; bindableProp: boolean } = $props();

https://svelte.dev/docs/svelte/$props

$props
();
import type { import LayoutDataLayoutData } from './$types';

let { let data: LayoutDatadata, let children: Snippetchildren }: { data: LayoutDatadata: import LayoutDataLayoutData, children: Snippetchildren: type Snippet = /*unresolved*/ anySnippet } = 
function $props(): any
namespace $props

Declares the props that a component accepts. Example:

let { optionalProp = 42, requiredProp, bindableProp = $bindable() }: { optionalProp?: number; requiredProps: string; bindableProp: boolean } = $props();

https://svelte.dev/docs/svelte/$props

$props
();

依次注释 load 函数为 PageLoadPageServerLoadLayoutLoadLayoutServerLoad(分别对应于 +page.js+page.server.js+layout.js+layout.server.js),确保 params 和返回值类型正确。

如果您正在使用 VS Code 或支持语言服务器协议和 TypeScript 插件的任何 IDE,那么您可以完全省略这些类型!Svelte 的 IDE 工具将为您插入正确的类型,因此您将获得类型检查而无需自己编写。它还与我们的命令行工具 svelte-check 一起工作。

您可以在我们的博客文章中了解更多关于省略$types的信息。

其他文件

任何位于路由目录内的其他文件都将被 SvelteKit 忽略。这意味着您可以将组件和需要它们的实用模块与路由一起放置。

如果组件和模块被多个路由需要,将它们放在$lib中是个好主意。

进一步阅读

Edit this page on GitHub llms.txt