路由
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)渲染后续导航。
<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>
页面可以通过data
属性从load
函数接收数据。
<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
函数
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
。
除了load
之外,+page.js
还可以导出配置页面行为的值
export const prerender = true
或false
或'auto'
export const ssr = true
或false
export const csr = true
或false
你可以在页面选项中找到有关这些内容的更多信息。
+page.server.js
如果你的load
函数只能在服务器上运行——例如,如果它需要从数据库中获取数据或你需要访问私有环境变量(如 API 密钥)——那么你可以将+page.js
重命名为+page.server.js
并将PageLoad
类型更改为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
。
与+page.js
一样,+page.server.js
可以导出页面选项——prerender
、ssr
和csr
。
+page.server.js
文件还可以导出操作。如果load
允许你从服务器读取数据,则actions
允许你使用<form>
元素将数据写入服务器。要了解如何使用它们,请参阅表单操作 部分。
+error
如果在load
期间发生错误,SvelteKit 将渲染一个默认错误页面。你可以通过添加+error.svelte
文件在每个路由的基础上自定义此错误页面
<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
上方的根+layout
的load
函数中抛出的),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
标签。例如,让我们添加一个导航栏
<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
创建页面…
<h1>Home</h1>
<h1>About</h1>
<h1>Settings</h1>
…导航栏将始终可见,并且在三个页面之间切换只会导致<h1>
被替换。
布局可以嵌套。假设我们不仅仅有一个/settings
页面,而是有嵌套页面,例如/settings/profile
和/settings/notifications
,它们具有共享的子菜单(有关实际示例,请参阅github.com/settings)。
我们可以创建一个仅适用于/settings
下的页面的布局(同时继承具有顶级导航的根布局)
<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
函数获取数据。
/** @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
——它们将用作子页面的默认值。
从布局的load
函数返回的数据也可用于其所有子页面
<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
和csr
。
+server
除了页面,您还可以使用+server.js
文件(有时称为“API 路由”或“端点”)定义路由,这使您可以完全控制响应。您的+server.js
文件导出与HTTP动词(如GET
、POST
、PATCH
、PUT
、DELETE
、OPTIONS
和HEAD
)相对应的函数,这些函数接受一个RequestEvent
参数并返回一个Response
对象。
例如,我们可以创建一个具有GET
处理程序的/api/random-number
路由
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)。
您可以使用来自@sveltejs/kit
的error
、redirect
和json
方法来方便操作(但您不必这样做)。
如果抛出错误(error(...)
或意外错误),响应将是错误的JSON表示形式或备用错误页面——可以通过src/error.html
自定义——具体取决于Accept
标头。在这种情况下,+error.svelte
组件**不会**渲染。您可以在这里阅读更多关于错误处理的信息。
在创建
OPTIONS
处理程序时,请注意Vite将注入Access-Control-Allow-Origin
和Access-Control-Allow-Methods
标头——除非您添加它们,否则这些标头在生产环境中将不存在。
接收数据
通过导出POST
/ PUT
/PATCH
/DELETE
/OPTIONS
/HEAD
处理程序,+server.js
文件可以用来创建一个完整的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>
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);
};
通常,表单操作是从浏览器向服务器提交数据的更好方法。
如果导出了
GET
处理程序,则HEAD
请求将返回GET
处理程序响应正文的content-length
。
回退方法处理程序
导出fallback
处理程序将匹配任何未处理的请求方法,包括MOVE
等没有从+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
处理程序。
内容协商
+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
返回的任何内容
<script>
/** @type {{ data: import('./$types').PageData }} */
let { data } = $props();
</script>
<script lang="ts">
import type { PageData } from './$types';
let { data }: { data: PageData } = $props();
</script>
依次,使用PageLoad
、PageServerLoad
、LayoutLoad
或LayoutServerLoad
(分别用于+page.js
、+page.server.js
、+layout.js
和+layout.server.js
)注释load
函数,确保params
和返回值的类型正确。
如果您使用的是VS Code或任何支持语言服务器协议和TypeScript插件的IDE,则可以完全省略这些类型!Svelte的IDE工具将为您插入正确的类型,因此您无需自己编写即可获得类型检查。它也适用于我们的命令行工具svelte-check
。
您可以在我们关于此主题的博客文章中阅读更多关于省略$types
的信息。
其他文件
SvelteKit会忽略路由目录内的任何其他文件。这意味着您可以将组件和实用程序模块与需要它们的路由放在一起。
如果多个路由需要组件和模块,最好将它们放在$lib
中。