跳到主要內容

路由

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

通常,頁面在渲染之前需要載入一些資料。為此,我們新增一個匯出 load 函數的 +page.js 模組

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 同時執行,這表示它在伺服器端渲染期間在伺服器上執行,並在客戶端導航期間在瀏覽器中執行。請參閱 load 以取得 API 的完整詳細資訊。

除了 load 之外,+page.js 可以匯出配置頁面行為的值

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

您可以在頁面選項中找到有關這些的更多資訊。

+page.server.js

如果您的 load 函數只能在伺服器上執行 — 例如,如果它需要從資料庫中提取資料,或者您需要存取私有的環境變數(例如 API 金鑰)— 那麼您可以將 +page.js 重新命名為 +page.server.js,並將 PageLoad 類型變更為 PageServerLoad

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

在客戶端導航期間,SvelteKit 將從伺服器載入此資料,這表示傳回的值必須可使用 devalue 進行序列化。請參閱 load 以取得 API 的完整詳細資訊。

+page.js 類似,+page.server.js 可以匯出頁面選項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,然後再渲染預設的錯誤頁面。如果操作失敗(或者錯誤是從根 +layoutload 函數擲出的,它位於根 +error「之上」),SvelteKit 將會退出並渲染靜態的回退錯誤頁面,您可以透過建立 src/error.html 檔案來自訂此頁面。

如果錯誤發生在 +layout(.server).js 中的 load 函數內,則樹狀結構中最接近的錯誤邊界是位於該版面配置上方+error.svelte 檔案(而不是與其相鄰)。

如果找不到路由 (404),將會使用 src/routes/+error.svelte(或者如果該檔案不存在,則使用預設的錯誤頁面)。

當錯誤發生在 handle+server.js 請求處理常式內時,不會使用 +error.svelte

您可以在這裡閱讀有關錯誤處理的更多資訊。

+layout

到目前為止,我們將頁面視為完全獨立的元件 — 導航時,現有的 +page.svelte 元件將被銷毀,並且新的元件將取而代之。

但在許多應用程式中,有些元素應該在每個頁面上都可見,例如最上層的導航或頁尾。我們可以將它們放在版面配置中,而不是在每個 +page.svelte 中重複它們。

+layout.svelte

若要建立適用於每個頁面的版面配置,請建立一個名為 src/routes/+layout.svelte 的檔案。預設版面配置(如果您不自行帶入,則 SvelteKit 會使用的版面配置)如下所示...

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

{@render children()}

...但是我們可以新增我們想要的任何標記、樣式和行為。唯一的要求是元件必須包含用於頁面內容的 @render 標籤。例如,讓我們新增一個導覽列

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

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

{@render children()}

如果我們為 //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(或 +layout.svelte 檔案的 LayoutData)註解 let { data } = $props() 會告知 TypeScript data 的類型是從 load 回傳的任何內容。

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

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

反之,使用 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 上編輯此頁面

上一頁 下一頁