路由
SvelteKit 的核心是一个基于文件系统的路由。应用的路由(即用户可以访问的 URL 路径)由代码库中的目录定义:
¥At the heart of SvelteKit is a filesystem-based router. The routes of your app — i.e. the URL paths that users can access — are defined by the directories in your codebase:
src/routes
是根路由¥
src/routes
is the root routesrc/routes/about
创建/about
路由¥
src/routes/about
creates an/about
routesrc/routes/blog/[slug]
创建一个带有参数slug
的路由,当用户请求页面(如/blog/hello-world
)时,该路由可用于动态加载数据¥
src/routes/blog/[slug]
creates a route with a parameter,slug
, that can be used to load data dynamically when a user requests a page like/blog/hello-world
你可以通过编辑 项目配置 将
src/routes
更改为不同的目录。¥[!NOTE] You can change
src/routes
to a different directory by editing the project config.
每个路由目录包含一个或多个路由文件,可以通过其 +
前缀来识别。
¥Each route directory contains one or more route files, which can be identified by their +
prefix.
我们稍后会更详细地介绍这些文件,但这里有一些简单的规则可以帮助你记住 SvelteKit 的路由工作原理:
¥We’ll introduce these files in a moment in more detail, but here are a few simple rules to help you remember how SvelteKit’s routing works:
所有文件都可以在服务器上运行
¥All files can run on the server
除
+server
文件外,所有文件都在客户端上运行¥All files run on the client except
+server
files+layout
和+error
文件适用于子目录以及它们所在的目录¥
+layout
and+error
files apply to subdirectories as well as the directory they live in
+page
+page.svelte
+page.svelte
组件定义应用的页面。默认情况下,页面在服务器(SSR)上渲染初始请求,并在浏览器(CSR)上渲染后续导航。
¥A +page.svelte
component defines a page of your app. By default, pages are rendered both on the server (SSR) for the initial request and in the browser (CSR) for subsequent navigation.
<h1>Hello and welcome to my site!</h1>
<a href="/about">About my site</a>
<h1>About this site</h1>
<p>TODO...</p>
<a href="/">Home</a>
SvelteKit 使用
<a>
元素在路由之间导航,而不是使用特定于框架的<Link>
组件。¥[!NOTE] SvelteKit uses
<a>
elements to navigate between routes, rather than a framework-specific<Link>
component.
页面可以通过 data
prop 从 load
函数接收数据。
¥Pages can receive data from load
functions via the data
prop.
<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>
Legacy mode
PageProps
是在 2.16.0 中添加的。在早期版本中,你必须手动输入data
属性,而使用PageData
,请参阅 $types。¥[!LEGACY]
PageProps
was added in 2.16.0. In earlier versions, you had to type thedata
property manually withPageData
instead, see $types.在 Svelte 4 中,你将使用
export let data
。¥In Svelte 4, you’d use
export let data
instead.
+page.js
通常,页面需要加载一些数据才能渲染。为此,我们添加了一个导出 load
函数的 +page.js
模块:
¥Often, a page will need to load some data before it can be rendered. For this, we add a +page.js
module that exports a load
function:
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.
error } from '@sveltejs/kit';
/** @type {import('./$types').PageLoad} */
export function function load({ params }: {
params: any;
}): {
title: string;
content: string;
}
load({ params: any
params }) {
if (params: any
params.slug === 'hello-world') {
return {
title: string
title: 'Hello world!',
content: string
content: '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.
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.
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: PageLoad
load: 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: string
title: 'Hello world!',
content: string
content: '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.
error(404, 'Not found');
};
此函数与 +page.svelte
一起运行,这意味着它在服务器端渲染期间在服务器上运行,在客户端导航期间在浏览器中运行。有关 API 的完整详细信息,请参阅 load
。
¥This function runs alongside +page.svelte
, which means it runs on the server during server-side rendering and in the browser during client-side navigation. See load
for full details of the API.
与 load
一样,+page.js
可以导出配置页面行为的值:
¥As well as load
, +page.js
can export values that configure the page’s behaviour:
export const prerender = true
或false
或'auto'
¥
export const prerender = true
orfalse
or'auto'
export const ssr = true
或false
¥
export const ssr = true
orfalse
export const csr = true
或false
¥
export const csr = true
orfalse
你可以在 页面选项 中找到有关这些的更多信息。
¥You can find more information about these in page options.
+page.server.js
如果你的 load
函数只能在服务器上运行 - 例如,如果它需要从数据库获取数据,或者你需要访问私有 环境变量(如 API 密钥),那么你可以将 +page.js
重命名为 +page.server.js
,并将 PageLoad
类型更改为 PageServerLoad
。
¥If your load
function can only run on the server — for example, if it needs to fetch data from a database or you need to access private environment variables like API keys — then you can rename +page.js
to +page.server.js
and change the PageLoad
type to PageServerLoad
.
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.
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>>
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.
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.
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: PageServerLoad
load: 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.
error(404, 'Not found');
};
在客户端导航期间,SvelteKit 将从服务器加载此数据,这意味着返回的值必须使用 devalue 进行序列化。有关 API 的完整详细信息,请参阅 load
。
¥During client-side navigation, SvelteKit will load this data from the server, which means that the returned value must be serializable using devalue. See load
for full details of the API.
与 +page.js
一样,+page.server.js
可以导出 页面选项 — prerender
、ssr
和 csr
。
¥Like +page.js
, +page.server.js
can export page options — prerender
, ssr
and csr
.
+page.server.js
文件还可以导出操作。如果 load
允许你从服务器读取数据,则 actions
允许你使用 <form>
元素将数据写入服务器。要了解如何使用它们,请参阅 表单操作 部分。
¥A +page.server.js
file can also export actions. If load
lets you read data from the server, actions
let you write data to the server using the <form>
element. To learn how to use them, see the form actions section.
+error
如果在 load
期间发生错误,SvelteKit 将渲染默认错误页面。你可以通过添加 +error.svelte
文件在每个路由的基础上自定义此错误页面:
¥If an error occurs during load
, SvelteKit will render a default error page. You can customise this error page on a per-route basis by adding an +error.svelte
file:
<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
SvelteKit 2.12 中添加了
$app/state
。如果你使用的是早期版本或使用 Svelte 4,请改用$app/stores
。¥[!LEGACY]
$app/state
was added in SvelteKit 2.12. If you’re using an earlier version or are using Svelte 4, use$app/stores
instead.
SvelteKit 将 ‘沿着树走’ 寻找最近的错误边界 - 如果上面的文件不存在,它会在渲染默认错误页面之前尝试 src/routes/blog/+error.svelte
然后 src/routes/+error.svelte
。如果失败(或者错误是从根 +layout
的 load
函数抛出的,该函数位于根 +error
的 ‘above’ 上),SvelteKit 将退出并渲染静态后备错误页面,你可以通过创建 src/error.html
文件对其进行自定义。
¥SvelteKit will ‘walk up the tree’ looking for the closest error boundary — if the file above didn’t exist it would try src/routes/blog/+error.svelte
and then src/routes/+error.svelte
before rendering the default error page. If that fails (or if the error was thrown from the load
function of the root +layout
, which sits ‘above’ the root +error
), SvelteKit will bail out and render a static fallback error page, which you can customise by creating a src/error.html
file.
如果错误发生在 +layout(.server).js
中的 load
函数内,则树中最近的错误边界是该布局上方(而不是旁边)的 +error.svelte
文件。
¥If the error occurs inside a load
function in +layout(.server).js
, the closest error boundary in the tree is an +error.svelte
file above that layout (not next to it).
如果找不到路由(404),则将使用 src/routes/+error.svelte
(或默认错误页面,如果该文件不存在)。
¥If no route can be found (404), src/routes/+error.svelte
(or the default error page, if that file does not exist) will be used.
当
handle
或 +server.js 请求处理程序内部发生错误时,不使用+error.svelte
。¥[!NOTE]
+error.svelte
is not used when an error occurs insidehandle
or a +server.js request handler.
你可以阅读有关错误处理 此处 的更多信息。
¥You can read more about error handling here.
+layout
到目前为止,我们将页面视为完全独立的组件 - 导航时,现有的 +page.svelte
组件将被销毁,新的组件将取而代之。
¥So far, we’ve treated pages as entirely standalone components — upon navigation, the existing +page.svelte
component will be destroyed, and a new one will take its place.
但是在许多应用中,有些元素应该在每个页面上都可见,例如顶层导航或页脚。我们可以将它们放在布局中,而不是在每个 +page.svelte
中重复它们。
¥But in many apps, there are elements that should be visible on every page, such as top-level navigation or a footer. Instead of repeating them in every +page.svelte
, we can put them in layouts.
+layout.svelte
要创建适用于每个页面的布局,请创建一个名为 src/routes/+layout.svelte
的文件。默认布局(如果你没有自带,SvelteKit 会使用这个)如下所示...
¥To create a layout that applies to every page, make a file called src/routes/+layout.svelte
. The default layout (the one that SvelteKit uses if you don’t bring your own) looks like this...
<script>
let { children } = $props();
</script>
{@render children()}
...但是我们可以添加我们想要的任何标记、样式和行为。唯一的要求是组件包含页面内容的 @render
标签。例如,让我们添加一个导航栏:
¥...but we can add whatever markup, styles and behaviour we want. The only requirement is that the component includes a @render
tag for the page content. For example, let’s add a nav bar:
<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
创建页面...
¥If we create pages for /
, /about
and /settings
...
<h1>Home</h1>
<h1>About</h1>
<h1>Settings</h1>
...导航将始终可见,并且在三个页面之间单击只会导致 <h1>
被替换。
¥...the nav will always be visible, and clicking between the three pages will only result in the <h1>
being replaced.
布局可以嵌套。假设我们不只有一个 /settings
页面,而是有嵌套页面,如 /settings/profile
和 /settings/notifications
,并带有共享子菜单(有关实际示例,请参阅 github.com/settings)。
¥Layouts can be nested. Suppose we don’t just have a single /settings
page, but instead have nested pages like /settings/profile
and /settings/notifications
with a shared submenu (for a real-life example, see github.com/settings).
我们可以创建一个仅适用于 /settings
以下页面的布局(同时使用顶层导航继承根布局):
¥We can create a layout that only applies to pages below /settings
(while inheriting the root layout with the top-level nav):
<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()}
Legacy mode
LayoutProps
是在 2.16.0 中添加的。在早期版本中,你必须 改为手动输入属性。¥[!LEGACY]
LayoutProps
was added in 2.16.0. In earlier versions, you had to type the properties manually instead.
你可以通过查看下面下一节中的 +layout.js
示例来了解 data
是如何填充的。
¥You can see how data
is populated by looking at the +layout.js
example in the next section just below.
默认情况下,每个布局都会继承其上方的布局。有时这不是你想要的 - 在这种情况下,高级布局 可以帮助你。
¥By default, each layout inherits the layout above it. Sometimes that isn’t what you want - in this case, advanced layouts can help you.
+layout.js
就像 +page.svelte
从 +page.js
加载数据一样,你的 +layout.svelte
组件可以从 +layout.js
中的 load
函数获取数据。
¥Just like +page.svelte
loading data from +page.js
, your +layout.svelte
component can get data from a load
function in +layout.js
.
/** @type {import('./$types').LayoutLoad} */
export function function load(): {
sections: {
slug: string;
title: string;
}[];
}
load() {
return {
sections: {
slug: string;
title: string;
}[]
sections: [
{ slug: string
slug: 'profile', title: string
title: 'Profile' },
{ slug: string
slug: 'notifications', title: string
title: '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: LayoutLoad
load: 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: string
slug: 'profile', title: string
title: 'Profile' },
{ slug: string
slug: 'notifications', title: string
title: 'Notifications' }
]
};
};
如果 +layout.js
导出 页面选项 — prerender
、ssr
和 csr
— 它们将用作子页面的默认值。
¥If a +layout.js
exports page options — prerender
, ssr
and csr
— they will be used as defaults for child pages.
布局的 load
函数返回的数据也可用于其所有子页面:
¥Data returned from a layout’s load
function is also available to all its child pages:
<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 将在必要时智能地重新运行
load
函数。¥[!NOTE] Often, layout data is unchanged when navigating between pages. SvelteKit will intelligently rerun
load
functions when necessary.
+layout.server.js
要在服务器上运行布局的 load
函数,请将其移动到 +layout.server.js
,并将 LayoutLoad
类型更改为 LayoutServerLoad
。
¥To run your layout’s load
function on the server, move it to +layout.server.js
, and change the LayoutLoad
type to LayoutServerLoad
.
与 +layout.js
一样,+layout.server.js
可以导出 页面选项 — prerender
、ssr
和 csr
。
¥Like +layout.js
, +layout.server.js
can export page options — prerender
, ssr
and csr
.
+server
与页面一样,你还可以使用 +server.js
文件(有时称为 ‘API 路由’ 或 ‘endpoint’)定义路由,从而完全控制响应。你的 +server.js
文件导出与 HTTP 动词(如 GET
、POST
、PATCH
、PUT
、DELETE
、OPTIONS
和 HEAD
)相对应的函数,这些函数接受 RequestEvent
参数并返回 Response
对象。
¥As well as pages, you can define routes with a +server.js
file (sometimes referred to as an ‘API route’ or an ‘endpoint’), which gives you full control over the response. Your +server.js
file exports functions corresponding to HTTP verbs like GET
, POST
, PATCH
, PUT
, DELETE
, OPTIONS
, and HEAD
that take a RequestEvent
argument and return a Response
object.
例如,我们可以创建一个带有 GET
处理程序的 /api/random-number
路由:
¥For example we could create an /api/random-number
route with a GET
handler:
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.
error } from '@sveltejs/kit';
/** @type {import('./$types').RequestHandler} */
export function function GET({ url }: {
url: any;
}): Response
GET({ url: any
url }) {
const const min: number
min = 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: any
url.searchParams.get('min') ?? '0');
const const max: number
max = 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: any
url.searchParams.get('max') ?? '1');
const const d: number
d = const max: number
max - const min: number
min;
if (function isNaN(number: number): boolean
Returns a Boolean value that indicates whether a value is the reserved value NaN (not a number).
isNaN(const d: number
d) || const d: number
d < 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.
error(400, 'min and max must be numbers, and min must be less than max');
}
const const random: number
random = const min: number
min + 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: number
d;
return new var Response: new (body?: BodyInit | null, init?: ResponseInit) => Response
This Fetch API interface represents the response to a request.
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: number
random));
}
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.
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: RequestHandler
GET: 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: number
min = 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: URLSearchParams
searchParams.URLSearchParams.get(name: string): string | null
Returns the first value associated to the given search parameter.
get('min') ?? '0');
const const max: number
max = 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: URLSearchParams
searchParams.URLSearchParams.get(name: string): string | null
Returns the first value associated to the given search parameter.
get('max') ?? '1');
const const d: number
d = const max: number
max - const min: number
min;
if (function isNaN(number: number): boolean
Returns a Boolean value that indicates whether a value is the reserved value NaN (not a number).
isNaN(const d: number
d) || const d: number
d < 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.
error(400, 'min and max must be numbers, and min must be less than max');
}
const const random: number
random = const min: number
min + 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: number
d;
return new var Response: new (body?: BodyInit | null, init?: ResponseInit) => Response
This Fetch API interface represents the response to a request.
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: number
random));
};
Response
的第一个参数可以是 ReadableStream
,从而可以传输大量数据或创建服务器发送的事件(除非部署到缓冲响应的平台,如 AWS Lambda)。
¥The first argument to Response
can be a ReadableStream
, making it possible to stream large amounts of data or create server-sent events (unless deploying to platforms that buffer responses, like AWS Lambda).
为了方便起见,你可以使用 @sveltejs/kit
中的 error
、redirect
和 json
方法(但你不必这样做)。
¥You can use the error
, redirect
and json
methods from @sveltejs/kit
for convenience (but you don’t have to).
如果抛出错误(error(...)
或意外错误),响应将是错误的 JSON 表示或后备错误页面(可通过 src/error.html
进行自定义),具体取决于 Accept
标头。在这种情况下,+error.svelte
组件将不会被渲染。你可以阅读有关错误处理 此处 的更多信息。
¥If an error is thrown (either error(...)
or an unexpected error), the response will be a JSON representation of the error or a fallback error page — which can be customised via src/error.html
— depending on the Accept
header. The +error.svelte
component will not be rendered in this case. You can read more about error handling here.
创建
OPTIONS
处理程序时,请注意 Vite 将注入Access-Control-Allow-Origin
和Access-Control-Allow-Methods
标头 - 除非你添加它们,否则这些标头不会出现在生产中。¥[!NOTE] When creating an
OPTIONS
handler, note that Vite will injectAccess-Control-Allow-Origin
andAccess-Control-Allow-Methods
headers — these will not be present in production unless you add them.
+layout
文件对+server.js
文件没有影响。如果你想在每次请求之前运行一些逻辑,请将其添加到服务器handle
钩子。¥[!NOTE]
+layout
files have no effect on+server.js
files. If you want to run some logic before each request, add it to the serverhandle
hook.
接收数据(Receiving data)
¥Receiving data
通过导出 POST
/ PUT
/PATCH
/DELETE
/OPTIONS
/HEAD
处理程序,+server.js
文件可用于创建完整的 API:
¥By exporting POST
/ PUT
/PATCH
/DELETE
/OPTIONS
/HEAD
handlers, +server.js
files can be used to create a complete API:
<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>
import { function json(data: any, init?: ResponseInit | undefined): Response
Create a JSON Response
object from the supplied data.
json } from '@sveltejs/kit';
/** @type {import('./$types').RequestHandler} */
export async function function POST({ request }: {
request: any;
}): Promise<Response>
POST({ request: any
request }) {
const { const a: any
a, const b: any
b } = await request: any
request.json();
return function json(data: any, init?: ResponseInit | undefined): Response
Create a JSON Response
object from the supplied data.
json(const a: any
a + const b: any
b);
}
import { function json(data: any, init?: ResponseInit | undefined): Response
Create a JSON Response
object from the supplied data.
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: RequestHandler
POST: 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: any
a, const b: any
b } = 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.
json(const a: any
a + const b: any
b);
};
通常,表单操作 是从浏览器向服务器提交数据的更好方法。
¥[!NOTE] In general, form actions are a better way to submit data from the browser to the server.
如果导出了
GET
处理程序,HEAD
请求将返回GET
处理程序响应主体的content-length
。¥[!NOTE] If a
GET
handler is exported, aHEAD
request will return thecontent-length
of theGET
handler’s response body.
后备方法处理程序(Fallback method handler)
¥Fallback method handler
导出 fallback
处理程序将匹配任何未处理的请求方法,包括没有从 +server.js
导出的专用方法(如 MOVE
)。
¥Exporting the fallback
handler will match any unhandled request methods, including methods like MOVE
which have no dedicated export from +server.js
.
import { function json(data: any, init?: ResponseInit | undefined): Response
Create a JSON Response
object from the supplied data.
json, function text(body: string, init?: ResponseInit | undefined): Response
Create a Response
object from the supplied body.
text } from '@sveltejs/kit';
export async function function POST({ request }: {
request: any;
}): Promise<Response>
POST({ request: any
request }) {
const { const a: any
a, const b: any
b } = await request: any
request.json();
return function json(data: any, init?: ResponseInit | undefined): Response
Create a JSON Response
object from the supplied data.
json(const a: any
a + const b: any
b);
}
// This handler will respond to PUT, PATCH, DELETE, etc.
/** @type {import('./$types').RequestHandler} */
export async function function fallback({ request }: {
request: any;
}): Promise<Response>
fallback({ request: any
request }) {
return function text(body: string, init?: ResponseInit | undefined): Response
Create a Response
object from the supplied body.
text(`I caught your ${request: any
request.method} request!`);
}
import { function json(data: any, init?: ResponseInit | undefined): Response
Create a JSON Response
object from the supplied data.
json, function text(body: string, init?: ResponseInit | undefined): Response
Create a Response
object from the supplied body.
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: any
request }) {
const { const a: any
a, const b: any
b } = await request: any
request.json();
return function json(data: any, init?: ResponseInit | undefined): Response
Create a JSON Response
object from the supplied data.
json(const a: any
a + const b: any
b);
}
// This handler will respond to PUT, PATCH, DELETE, etc.
export const const fallback: RequestHandler
fallback: 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.
text(`I caught your ${request: Request
The original request object
request.Request.method: string
Returns request’s HTTP method, which is “GET” by default.
method} request!`);
};
对于
HEAD
请求,GET
处理程序优先于fallback
处理程序。¥[!NOTE] For
HEAD
requests, theGET
handler takes precedence over thefallback
handler.
内容协商(Content negotiation)
¥Content negotiation
+server.js
文件可以放在与 +page
文件相同的目录中,允许相同的路由成为页面或 API 端点。要确定哪个,SvelteKit 应用以下规则:
¥+server.js
files can be placed in the same directory as +page
files, allowing the same route to be either a page or an API endpoint. To determine which, SvelteKit applies the following rules:
PUT
/PATCH
/DELETE
/OPTIONS
请求始终由+server.js
处理,因为它们不适用于页面¥
PUT
/PATCH
/DELETE
/OPTIONS
requests are always handled by+server.js
since they do not apply to pages如果
accept
标头优先考虑text/html
(换句话说,它是浏览器页面请求),则GET
/POST
/HEAD
请求将被视为页面请求,否则它们将由+server.js
处理。¥
GET
/POST
/HEAD
requests are treated as page requests if theaccept
header prioritisestext/html
(in other words, it’s a browser page request), else they are handled by+server.js
.对
GET
请求的响应将包含Vary: Accept
标头,以便代理和浏览器分别缓存 HTML 和 JSON 响应。¥Responses to
GET
requests will include aVary: Accept
header, so that proxies and browsers cache HTML and JSON responses separately.
$types
在上述示例中,我们一直在从 $types.d.ts
文件导入类型。如果你使用 TypeScript(或带有 JSDoc 类型注释的 JavaScript),这是 SvelteKit 在隐藏目录中为你创建的文件,以便在使用根文件时为你提供类型安全。
¥Throughout the examples above, we’ve been importing types from a $types.d.ts
file. This is a file SvelteKit creates for you in a hidden directory if you’re using TypeScript (or JavaScript with JSDoc type annotations) to give you type safety when working with your root files.
例如,用 PageProps
(或 +layout.svelte
文件的 LayoutProps
)注释 let { data } = $props()
会告诉 TypeScript data
的类型是从 load
返回的任何类型:
¥For example, annotating let { data } = $props()
with PageProps
(or LayoutProps
, for a +layout.svelte
file) tells TypeScript that the type of data
is whatever was returned from load
:
<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 中添加的
PageProps
和LayoutProps
类型是将data
属性键入为PageData
或LayoutData
的快捷方式,以及其他属性,例如页面的form
或布局的children
。在早期版本中,你必须手动输入这些属性。例如,对于页面:¥[!NOTE] The
PageProps
andLayoutProps
types, added in 2.16.0, are a shortcut for typing thedata
prop asPageData
orLayoutData
, as well as other props, such asform
for pages, orchildren
for layouts. In earlier versions, you had to type these properties manually. For example, for a page:+page/** @type {{ data: import('./$types').PageData, form: import('./$types').ActionData }} */ let {
let data: any
data,let form: any
form } =function $props(): any
$props();Declares the props that a component accepts. Example:
let { optionalProp = 42, requiredProp, bindableProp = $bindable() }: { optionalProp?: number; requiredProps: string; bindableProp: boolean } = $props();
import type {
import PageData
PageData,import ActionData
ActionData } from './$types'; let {let data: PageData
data,let form: ActionData
form }: {data: PageData
data:import PageData
PageData,form: ActionData
form:import ActionData
ActionData } =function $props(): any
$props();Declares the props that a component accepts. Example:
let { optionalProp = 42, requiredProp, bindableProp = $bindable() }: { optionalProp?: number; requiredProps: string; bindableProp: boolean } = $props();
或者,对于布局:
¥Or, for a layout:
+layout/** @type {{ data: import('./$types').LayoutData, children: Snippet }} */ let {
let data: any
data,let children: any
children } =function $props(): any
$props();Declares the props that a component accepts. Example:
let { optionalProp = 42, requiredProp, bindableProp = $bindable() }: { optionalProp?: number; requiredProps: string; bindableProp: boolean } = $props();
import type {
import LayoutData
LayoutData } from './$types'; let {let data: LayoutData
data,let children: Snippet
children }: {data: LayoutData
data:import LayoutData
LayoutData,children: Snippet
children:type Snippet = /*unresolved*/ any
Snippet } =function $props(): any
$props();Declares the props that a component accepts. Example:
let { optionalProp = 42, requiredProp, bindableProp = $bindable() }: { optionalProp?: number; requiredProps: string; bindableProp: boolean } = $props();
反过来,用 PageLoad
、PageServerLoad
、LayoutLoad
或 LayoutServerLoad
(分别用于 +page.js
、+page.server.js
、+layout.js
和 +layout.server.js
)注释 load
函数可确保正确输入 params
和返回值。
¥In turn, annotating the load
function with PageLoad
, PageServerLoad
, LayoutLoad
or LayoutServerLoad
(for +page.js
, +page.server.js
, +layout.js
and +layout.server.js
respectively) ensures that params
and the return value are correctly typed.
如果你使用的是 VS Code 或任何支持语言服务器协议和 TypeScript 插件的 IDE,那么你可以完全省略这些类型!Svelte 的 IDE 工具将为你插入正确的类型,因此你无需自己编写类型检查即可进行类型检查。它还可以与我们的命令行工具 svelte-check
一起使用。
¥If you’re using VS Code or any IDE that supports the language server protocol and TypeScript plugins then you can omit these types entirely! Svelte’s IDE tooling will insert the correct types for you, so you’ll get type checking without writing them yourself. It also works with our command line tool svelte-check
.
你可以在我们的 博客文章 中阅读有关省略 $types
的更多信息。
¥You can read more about omitting $types
in our blog post about it.
其他文件(Other files)
¥Other files
SvelteKit 会忽略路由目录中的任何其他文件。这意味着你可以将组件和实用程序模块与需要它们的路由共置。
¥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.
如果多个路由需要组件和模块,最好将它们放在 $lib
中。
¥If components and modules are needed by multiple routes, it’s a good idea to put them in $lib
.
进一步阅读(Further reading)
¥Further reading