跳至主要内容

路由

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>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>

页面可以通过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 文件还可以导出操作。如果load 允许你从服务器读取数据,则actions 允许你使用<form> 元素将数据写入服务器。要了解如何使用它们,请参阅表单操作 部分。

+error

如果在load 期间发生错误,SvelteKit 将渲染一个默认错误页面。你可以通过添加+error.svelte 文件在每个路由的基础上自定义此错误页面

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

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

SvelteKit 将“向上遍历树”寻找最近的错误边界——如果上面的文件不存在,它将尝试src/routes/blog/+error.svelte,然后尝试src/routes/+error.svelte,然后再渲染默认错误页面。如果失败了(或者如果错误是从位于“根”+error 上方的根+layoutload 函数中抛出的),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()}

如果我们为//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 {{ 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 可以导出页面选项——prerenderssrcsr

+server

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

例如,我们可以创建一个具有GET处理程序的/api/random-number路由

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,这使得流式传输大量数据或创建服务器发送事件成为可能(除非部署到缓冲响应的平台,如AWS Lambda)。

您可以使用来自@sveltejs/kiterrorredirectjson方法来方便操作(但您不必这样做)。

如果抛出错误(error(...)或意外错误),响应将是错误的JSON表示形式或备用错误页面——可以通过src/error.html自定义——具体取决于Accept标头。在这种情况下,+error.svelte组件**不会**渲染。您可以在这里阅读更多关于错误处理的信息

在创建OPTIONS处理程序时,请注意Vite将注入Access-Control-Allow-OriginAccess-Control-Allow-Methods标头——除非您添加它们,否则这些标头在生产环境中将不存在。

接收数据

通过导出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>
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请求将返回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处理,因为它们不适用于页面
  • 如果accept标头优先考虑text/html(换句话说,这是一个浏览器页面请求),则GET / POST/HEAD请求将被视为页面请求,否则它们将由+server.js处理。
  • GET请求的响应将包含一个Vary: Accept标头,以便代理和浏览器分别缓存HTML和JSON响应。

$types

在上面的所有示例中,我们一直在从$types.d.ts文件导入类型。如果您使用TypeScript(或带有JSDoc类型注释的JavaScript),SvelteKit会在隐藏目录中为您创建此文件,以便在使用根文件时提供类型安全性。

例如,使用PageData(或LayoutData,对于+layout.svelte文件)注释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>

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

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

您可以在我们关于此主题的博客文章中阅读更多关于省略$types的信息。

其他文件

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

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

进一步阅读

在GitHub上编辑此页面

上一页 下一页