Skip to main content

路由

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

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

您可以通过编辑项目配置来将 src/routes 更改为其他目录。

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

我们稍后会更详细地介绍这些文件,但这里有几个简单的规则可以帮助您记住 SvelteKit 的路由是如何工作的:

  • 所有文件都可以在服务端上运行
  • 除了 +server 文件外,所有文件都在客户端运行
  • +layout+error 文件不仅适用于它们所在的目录,也适用于子目录

+page

+page.svelte

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

src/routes/+page
<h1>您好,欢迎来到我的网站!</h1>
<a href="/about">关于我的网站</a>
src/routes/about/+page
<h1>关于本站</h1>
<p>待办...</p>
<a href="/">首页</a>

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

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

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

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

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

[!遗留模式] 在 Svelte 4 中,您需要使用 export let data 代替

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

+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 进行序列化。有关该 API 的完整详细信息,请参见 load

+page.js 类似,+page.server.js 可以导出页面选项 — prerenderssrcsr

+page.server.js 文件还可以导出 actions。如果 load 让您从服务端读取数据,那么 actions 让您使用 <form> 元素向服务端写入数据。要了解如何使用它们,请参阅 form actions 章节。

+error

如果在 load 期间发生错误,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>
Legacy mode

> $app/state 是在 SvelteKit 2.12 中添加的。如果你使用的是早期版本或正在使用 Svelte 4,请改用 $app/stores

SvelteKit 会”向上遍历”寻找最近的错误边界 —— 如果上面的文件不存在,它会尝试 src/routes/blog/+error.svelte 然后是 src/routes/+error.svelte,之后才会渲染默认错误页面。如果失败(或者如果错误是从根 +layoutload 函数抛出的,该函数位于根 +error 之上),SvelteKit 将退出并渲染一个静态的后备错误页面,你可以通过创建 src/error.html 文件来自定义它。

如果错误发生在 +layout(.server).js 中的 load 函数内,树中最近的错误边界是该布局上方的 +error.svelte 文件(而不是在其旁边)。

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

当错误发生在 handle+server.js 请求处理程序中时,不会使用 +error.svelte

您可以在这里阅读更多关于错误处理的内容。

+layout

到目前为止,我们将页面视为完全独立的组件 —— 在导航时,现有的 +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)。

We can create a layout that only applies to pages below /settings (while inheriting the root layout with the top-level nav):

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

src/routes/settings/+layout
<script>
  /** @type {{ data: import('./$types').LayoutData, children: import('svelte').Snippet }} */
  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 { LayoutData } from './$types';
	import type { Snippet } from 'svelte';

  let { data, children }: { data: LayoutData, children: Snippet } = $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()}

你可以通过查看下方下一节中的 +layout.js 示例来了解如何填充 data

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

+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 导出页面选项 - prerenderssrcsr - 它们将用作子页面的默认值。

布局的 load 函数返回的数据也可用于其所有子页面:

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

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

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

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

通常,在页面之间导航时布局数据保持不变。SvelteKit 会在必要时智能地重新运行 load 函数。

+layout.server.js

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

+layout.js 一样,+layout.server.js 可以导出页面选项prerender, ssr and csr.

+server

除了页面之外,你还可以使用 +server.js 文件(有时称为”API 路由”或"端点”)定义路由,这使你可以完全控制响应。你的 +server.js 文件导出对应 HTTP 动词的函数,如 GET, POST, PATCH, PUT, DELETE, OPTIONSHEAD,它们接受一个 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));
};

Response 的第一个参数可以是 ReadableStream,这使得可以流式传输大量数据或创建 server-sent events(除非部署到像 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 hook 中。

接收数据

通过导出 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);
};

一般来说,form actions 是从浏览器向服务端提交数据的更好方式。

如果导出了 GET 处理程序,HEAD 请求将返回 GET 处理程序响应体的content-length

后备方法处理程序

导出 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';
export async function
function POST({ request }: {
    request: any;
}): Promise<Response>
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 async function
function POST({ request }: {
    request: any;
}): Promise<Response>
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. 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 文件导入类型。如果您使用 TypeScript(或带有 JSDoc 类型注释的 JavaScript),SvelteKit 会在隐藏目录中为您创建这个文件,以便在处理根文件时提供类型安全。

例如,用 PageData(或者对于 +layout.svelte 文件使用 LayoutData)注释 let { data } = $props() 告诉 TypeScript,data 的类型就是从 load 返回的类型:

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

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

反过来,使用 load 函数并用 PageLoadPageServerLoadLayoutLoadLayoutServerLoad(分别对应 +page.js+page.server.js+layout.js+layout.server.js)进行注解,可以确保 params 和返回值被正确类型化。

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

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

其他文件

Any other files inside a route directory are ignored by SvelteKit. This means you can colocate components and utility modules with the routes that need them.

SvelteKit 会忽略路由目录中的任何其他文件。这意味着你可以将组件和工具模块与需要它们的路由放在一起。

If components and modules are needed by multiple routes, it’s a good idea to put them in $lib.

如果多个路由都需要这些组件和模块,最好将它们放在 $lib 中。

Further reading

在 GitHub 编辑此页面

上一页 下一页