跳至主要内容

加载数据

在渲染 +page.svelte 组件(及其包含的 +layout.svelte 组件)之前,我们通常需要获取一些数据。这是通过定义 load 函数来完成的。

页面数据

一个 +page.svelte 文件可以有一个同级 +page.js 文件,它导出一个 load 函数,该函数的返回值可通过 data 属性提供给页面

src/routes/blog/[slug]/+page
/** @type {import('./$types').PageLoad} */
export function 
function load({ params }: {
    params: any;
}): {
    post: {
        title: string;
        content: string;
    };
}
@type{import('./$types').PageLoad}
load
({ params: anyparams }) {
return {
post: {
    title: string;
    content: string;
}
post
: {
title: stringtitle: `Title for ${params: anyparams.slug} goes here`, content: stringcontent: `Content for ${params: anyparams.slug} goes here` } }; }
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
}) => {
return {
post: {
    title: string;
    content: string;
}
post
: {
title: stringtitle: `Title for ${params: Record<string, any>

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

params
.slug} goes here`,
content: stringcontent: `Content for ${params: Record<string, any>

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

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

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

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

<h1>{data.post.title}</h1>
<div>{@html data.post.content}</div>
传统模式

在 Svelte 4 中,您将使用 export let data 代替

由于生成的 $types 模块,我们获得了完整的类型安全性。

+page.js 文件中的 load 函数在服务器和浏览器中都会运行(除非与 export const ssr = false 结合使用,在这种情况下,它将 仅在浏览器中运行)。如果您的 load 函数应始终在服务器上运行(例如,因为它使用私有环境变量或访问数据库),则它应该放在 +page.server.js 中。

您博客文章的 load 函数的一个更真实的版本,它仅在服务器上运行并从数据库中提取数据,可能如下所示

src/routes/blog/[slug]/+page.server
import * as module "$lib/server/database"db from '$lib/server/database';

/** @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
}) {
return {
post: {
    title: string;
    content: string;
}
post
: await module "$lib/server/database"db.
function getPost(slug: string): Promise<{
    title: string;
    content: string;
}>
getPost
(params: Record<string, any>

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

params
.slug)
}; }
import * as module "$lib/server/database"db from '$lib/server/database';
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
}) => {
return {
post: {
    title: string;
    content: string;
}
post
: await module "$lib/server/database"db.
function getPost(slug: string): Promise<{
    title: string;
    content: string;
}>
getPost
(params: Record<string, any>

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

params
.slug)
}; };

请注意,类型已从 PageLoad 更改为 PageServerLoad,因为服务器 load 函数可以访问其他参数。要了解何时使用 +page.js 以及何时使用 +page.server.js,请参阅 通用与服务器端

布局数据

您的 +layout.svelte 文件也可以通过 +layout.js+layout.server.js 加载数据。

src/routes/blog/[slug]/+layout.server
import * as module "$lib/server/database"db from '$lib/server/database';

/** @type {import('./$types').LayoutServerLoad} */
export async function function load(event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').LayoutServerLoad}
load
() {
return {
posts: {
    title: string;
    slug: string;
}[]
posts
: await module "$lib/server/database"db.
function getPostSummaries(): Promise<Array<{
    title: string;
    slug: string;
}>>
getPostSummaries
()
}; }
import * as module "$lib/server/database"db from '$lib/server/database';
import type { type LayoutServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>LayoutServerLoad } from './$types';

export const const load: LayoutServerLoadload: type LayoutServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>LayoutServerLoad = async () => {
	return {
		
posts: {
    title: string;
    slug: string;
}[]
posts
: await module "$lib/server/database"db.
function getPostSummaries(): Promise<Array<{
    title: string;
    slug: string;
}>>
getPostSummaries
()
}; };
src/routes/blog/[slug]/+layout
<script>
	/** @type {{ data: import('./$types').LayoutData, children: Snippet }} */
	let { data, children } = $props();
</script>

<main>
	<!-- +page.svelte is `@render`ed here -->
	{@render children()}
</main>

<aside>
	<h2>More posts</h2>
	<ul>
		{#each data.posts as post}
			<li>
				<a href="/blog/{post.slug}">
					{post.title}
				</a>
			</li>
		{/each}
	</ul>
</aside>
<script lang="ts">
	import type { LayoutData } from './$types';

	let { data, children }: { data: LayoutData, children: Snippet } = $props();
</script>

<main>
	<!-- +page.svelte is `@render`ed here -->
	{@render children()}
</main>

<aside>
	<h2>More posts</h2>
	<ul>
		{#each data.posts as post}
			<li>
				<a href="/blog/{post.slug}">
					{post.title}
				</a>
			</li>
		{/each}
	</ul>
</aside>

从布局 load 函数返回的数据可用于子 +layout.svelte 组件和 +page.svelte 组件,以及它“所属”的布局。

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

	/** @type {{ data: import('./$types').PageData }} */
	let { data } = $props();

	// we can access `data.posts` because it's returned from
	// the parent layout `load` function
	let index = $derived(data.posts.findIndex(post => post.slug === $page.params.slug));
	let next = $derived(data.posts[index + 1]);
</script>

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

{#if next}
	<p>Next post: <a href="/blog/{next.slug}">{next.title}</a></p>
{/if}
<script lang="ts">
	import { page } from '$app/stores';
	import type { PageData } from './$types';

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

	// we can access `data.posts` because it's returned from
	// the parent layout `load` function
	let index = $derived(data.posts.findIndex(post => post.slug === $page.params.slug));
	let next = $derived(data.posts[index + 1]);
</script>

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

{#if next}
	<p>Next post: <a href="/blog/{next.slug}">{next.title}</a></p>
{/if}

如果多个 load 函数返回具有相同键的数据,则最后一个函数“获胜”——布局 load 返回 { a: 1, b: 2 } 和页面 load 返回 { b: 3, c: 4 } 的结果将为 { a: 1, b: 3, c: 4 }

$page.data

+page.svelte 组件及其上方的每个 +layout.svelte 组件都可以访问其自身数据以及其父级的所有数据。

在某些情况下,我们可能需要相反的情况——父布局可能需要访问页面数据或子布局的数据。例如,根布局可能希望访问 +page.js+page.server.jsload 函数返回的 title 属性。这可以通过 $page.data 完成

src/routes/+layout
<script>
	import { page } from '$app/stores';
</script>

<svelte:head>
	<title>{$page.data.title}</title>
</svelte:head>

$page.data 的类型信息由 App.PageData 提供。

通用与服务器端

正如我们所见,有两种类型的 load 函数

  • +page.js+layout.js 文件导出在服务器和浏览器中都运行的通用 load 函数
  • +page.server.js+layout.server.js 文件导出仅在服务器端运行的服务器端 load 函数

从概念上讲,它们是同一件事,但有一些重要的区别需要注意。

哪个加载函数何时运行?

服务器端 load 函数始终在服务器上运行。

默认情况下,通用 load 函数在用户首次访问页面时在服务器端 SSR 期间运行。然后,它们将在水合过程中再次运行,重用来自 fetch 请求 的任何响应。通用 load 函数的所有后续调用都在浏览器中发生。您可以通过 页面选项 自定义行为。如果您禁用 服务器端渲染,您将获得一个 SPA,并且通用 load 函数将始终在客户端运行。

如果一个路由同时包含通用和服务器端 load 函数,则服务器端 load 函数先运行。

除非您 预渲染 页面,否则 load 函数在运行时被调用——在这种情况下,它在构建时被调用。

输入

通用和服务器端 load 函数都可以访问描述请求的属性(paramsrouteurl)以及各种函数(fetchsetHeadersparentdependsuntrack)。这些将在以下部分中进行描述。

服务器端 load 函数被调用时会传递一个 ServerLoadEvent,它从 RequestEvent 继承 clientAddresscookieslocalsplatformrequest

通用 load 函数被调用时会传递一个 LoadEvent,它具有一个 data 属性。如果您在 +page.js+page.server.js(或 +layout.js+layout.server.js)中都有 load 函数,则服务器端 load 函数的返回值是通用 load 函数参数的 data 属性。

输出

通用 load 函数可以返回一个包含任何值的 对象,包括自定义类和组件构造函数等。

服务器端 load 函数必须返回可以使用 devalue 序列化的数据——任何可以表示为 JSON 的内容以及 BigIntDateMapSetRegExp 等内容,或重复/循环引用——以便可以通过网络传输。您的数据可以包含 Promise,在这种情况下,它将流式传输到浏览器。

何时使用哪个

当您需要直接从数据库或文件系统访问数据,或需要使用私有环境变量时,服务器端 load 函数很方便。

当您需要从外部 API fetch 数据并且不需要私有凭据时,通用 load 函数很有用,因为 SvelteKit 可以直接从 API 获取数据,而不是通过您的服务器。当您需要返回无法序列化的内容(例如 Svelte 组件构造函数)时,它们也很有用。

在极少数情况下,您可能需要将两者结合使用——例如,您可能需要返回一个使用服务器数据初始化的自定义类的实例。当同时使用两者时,服务器端 load 的返回值不会直接传递给页面,而是传递给通用 load 函数(作为 data 属性)

src/routes/+page.server
/** @type {import('./$types').PageServerLoad} */
export async function 
function load(): Promise<{
    serverMessage: string;
}>
@type{import('./$types').PageServerLoad}
load
() {
return { serverMessage: stringserverMessage: 'hello from server load function' }; }
import type { 
type PageServerLoad = (event: Kit.ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
type PageServerLoad = (event: Kit.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: Kit.ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
type PageServerLoad = (event: Kit.ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
PageServerLoad
= async () => {
return { serverMessage: stringserverMessage: 'hello from server load function' }; };
src/routes/+page
/** @type {import('./$types').PageLoad} */
export async function 
function load({ data }: {
    data: any;
}): Promise<{
    serverMessage: any;
    universalMessage: string;
}>
@type{import('./$types').PageLoad}
load
({ data: anydata }) {
return { serverMessage: anyserverMessage: data: anydata.serverMessage, universalMessage: stringuniversalMessage: 'hello from universal load function' }; }
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
= async ({ data: Record<string, any> | null

Contains the data returned by the route’s server load function (in +layout.server.js or +page.server.js), if any.

data
}) => {
return { serverMessage: anyserverMessage: data: Record<string, any> | null

Contains the data returned by the route’s server load function (in +layout.server.js or +page.server.js), if any.

data
.serverMessage,
universalMessage: stringuniversalMessage: 'hello from universal load function' }; };

使用 URL 数据

通常 load 函数以某种方式依赖于 URL。为此,load 函数为您提供了 urlrouteparams

url

一个 URL 实例,包含 originhostnamepathnamesearchParams 等属性(它包含作为 URLSearchParams 对象解析的查询字符串)。在 load 期间无法访问 url.hash,因为它在服务器上不可用。

在某些环境中,它是在服务器端渲染期间从请求头派生的。例如,如果您使用的是 adapter-node,则可能需要配置适配器才能使 URL 正确。

route

包含当前路由目录相对于 src/routes 的名称

src/routes/a/[b]/[...c]/+page
/** @type {import('./$types').PageLoad} */
export function 
function load({ route }: {
    route: any;
}): void
@type{import('./$types').PageLoad}
load
({ route: anyroute }) {
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without calling require('console').

Warning: The global console object’s methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
//   Error: Whoops, something bad happened
//     at [eval]:5:15
//     at Script.runInThisContext (node:vm:132:18)
//     at Object.runInThisContext (node:vm:309:38)
//     at node:internal/process/execution:77:19
//     at [eval]-wrapper:6:22
//     at evalScript (node:internal/process/execution:76:60)
//     at node:internal/main/eval_string:23:3

const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);

myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err

const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err
@seesource
console
.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100
log
(route: anyroute.id); // '/a/[b]/[...c]'
}
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
= ({
route: {
    id: string | null;
}

Info about the current route

route
}) => {
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without calling require('console').

Warning: The global console object’s methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
//   Error: Whoops, something bad happened
//     at [eval]:5:15
//     at Script.runInThisContext (node:vm:132:18)
//     at Object.runInThisContext (node:vm:309:38)
//     at node:internal/process/execution:77:19
//     at [eval]-wrapper:6:22
//     at evalScript (node:internal/process/execution:76:60)
//     at node:internal/main/eval_string:23:3

const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);

myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err

const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err
@seesource
console
.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100
log
(
route: {
    id: string | null;
}

Info about the current route

route
.id: string | null

The ID of the current route - e.g. for src/routes/blog/[slug], it would be /blog/[slug]

id
); // '/a/[b]/[...c]'
};

params

params 来自 url.pathnameroute.id

给定 route.id/a/[b]/[...c]url.pathname/a/x/y/z,则 params 对象将如下所示

{
	"b": "x",
	"c": "y/z"
}

发出 fetch 请求

要从外部 API 或 +server.js 处理程序获取数据,您可以使用提供的 fetch 函数,它的行为与 原生 fetch Web API 完全相同,并具有一些附加功能

  • 它可以在服务器上用于发出有凭据的请求,因为它继承了页面请求的 cookieauthorization 头。
  • 它可以在服务器上发出相对请求(通常,当在服务器上下文中使用时,fetch 需要一个带有原点的 URL)。
  • 内部请求(例如,用于 +server.js 路由)在服务器上运行时会直接转到处理程序函数,而无需 HTTP 调用的开销。
  • 在服务器端渲染期间,响应将被捕获并通过挂接到 Response 对象的 textjsonarrayBuffer 方法内联到渲染的 HTML 中。请注意,除非通过 filterSerializedResponseHeaders 显式包含,否则不会序列化标头。
  • 在水合过程中,响应将从 HTML 中读取,保证一致性并防止额外的网络请求——如果您在使用浏览器 fetch 而不是 load fetch 时在浏览器控制台中收到警告,这就是原因。
src/routes/items/[id]/+page
/** @type {import('./$types').PageLoad} */
export async function 
function load({ fetch, params }: {
    fetch: any;
    params: any;
}): Promise<{
    item: any;
}>
@type{import('./$types').PageLoad}
load
({ fetch: anyfetch, params: anyparams }) {
const const res: anyres = await fetch: anyfetch(`/api/items/${params: anyparams.id}`); const const item: anyitem = await const res: anyres.json(); return { item: anyitem }; }
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
= async ({
fetch: {
    (input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
    (input: string | URL | globalThis.Request, init?: RequestInit): Promise<Response>;
}

fetch is equivalent to the native fetch web API, with a few additional features:

  • It can be used to make credentialed requests on the server, as it inherits the cookie and authorization headers for the page request.
  • It can make relative requests on the server (ordinarily, fetch requires a URL with an origin when used in a server context).
  • Internal requests (e.g. for +server.js routes) go directly to the handler function when running on the server, without the overhead of an HTTP call.
  • During server-side rendering, the response will be captured and inlined into the rendered HTML by hooking into the text and json methods of the Response object. Note that headers will not be serialized, unless explicitly included via filterSerializedResponseHeaders
  • During hydration, the response will be read from the HTML, guaranteeing consistency and preventing an additional network request.

You can learn more about making credentialed requests with cookies here

fetch
, params: Record<string, any>

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

params
}) => {
const const res: Responseres = await fetch: (input: string | URL | globalThis.Request, init?: RequestInit) => Promise<Response> (+1 overload)fetch(`/api/items/${params: Record<string, any>

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

params
.id}`);
const const item: anyitem = await const res: Responseres.Body.json(): Promise<any>json(); return { item: anyitem }; };

Cookie

服务器端 load 函数可以获取和设置 cookies

src/routes/+layout.server
import * as module "$lib/server/database"db from '$lib/server/database';

/** @type {import('./$types').LayoutServerLoad} */
export async function function load(event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').LayoutServerLoad}
load
({ cookies: Cookies

Get or set cookies related to the current request

cookies
}) {
const const sessionid: string | undefinedsessionid = cookies: Cookies

Get or set cookies related to the current request

cookies
.Cookies.get(name: string, opts?: CookieParseOptions): string | undefined

Gets a cookie that was previously set with cookies.set, or from the request headers.

@paramname the name of the cookie
@paramopts the options, passed directly to cookie.parse. See documentation here
get
('sessionid');
return {
user: {
    name: string;
    avatar: string;
}
user
: await module "$lib/server/database"db.
function getUser(sessionid: string | undefined): Promise<{
    name: string;
    avatar: string;
}>
getUser
(const sessionid: string | undefinedsessionid)
}; }
import * as module "$lib/server/database"db from '$lib/server/database';
import type { type LayoutServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>LayoutServerLoad } from './$types';

export const const load: LayoutServerLoadload: type LayoutServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>LayoutServerLoad = async ({ cookies: Cookies

Get or set cookies related to the current request

cookies
}) => {
const const sessionid: string | undefinedsessionid = cookies: Cookies

Get or set cookies related to the current request

cookies
.Cookies.get(name: string, opts?: CookieParseOptions): string | undefined

Gets a cookie that was previously set with cookies.set, or from the request headers.

@paramname the name of the cookie
@paramopts the options, passed directly to cookie.parse. See documentation here
get
('sessionid');
return {
user: {
    name: string;
    avatar: string;
}
user
: await module "$lib/server/database"db.
function getUser(sessionid: string | undefined): Promise<{
    name: string;
    avatar: string;
}>
getUser
(const sessionid: string | undefinedsessionid)
}; };

只有当目标主机与 SvelteKit 应用程序相同或它是其更具体的子域名时,Cookie 才会通过提供的 fetch 函数传递。

例如,如果 SvelteKit 正在提供 my.domain.com

  • domain.com 将不会接收 Cookie
  • my.domain.com 将接收 Cookie

  • api.domain.com **不会**接收 Cookie
  • sub.my.domain.com **会**接收 Cookie

当设置 credentials: 'include' 时,其他 Cookie 不会被传递,因为 SvelteKit 不知道哪个 Cookie 属于哪个域名(浏览器不会传递此信息),因此转发任何 Cookie 都不安全。使用 handleFetch hook 来解决此问题。

Headers

服务器端和通用 load 函数都可以访问 setHeaders 函数,该函数在服务器端运行时可以设置响应的 Headers。(在浏览器中运行时,setHeaders 无效。)例如,如果您希望页面被缓存,这将非常有用。

src/routes/products/+page
/** @type {import('./$types').PageLoad} */
export async function 
function load({ fetch, setHeaders }: {
    fetch: any;
    setHeaders: any;
}): Promise<any>
@type{import('./$types').PageLoad}
load
({ fetch: anyfetch, setHeaders: anysetHeaders }) {
const const url: "https://cms.example.com/products.json"url = `https://cms.example.com/products.json`; const const response: anyresponse = await fetch: anyfetch(const url: "https://cms.example.com/products.json"url); // Headers are only set during SSR, caching the page's HTML // for the same length of time as the underlying data. setHeaders: anysetHeaders({ age: anyage: const response: anyresponse.headers.get('age'), 'cache-control': const response: anyresponse.headers.get('cache-control') }); return const response: anyresponse.json(); }
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
= async ({
fetch: {
    (input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
    (input: string | URL | globalThis.Request, init?: RequestInit): Promise<Response>;
}

fetch is equivalent to the native fetch web API, with a few additional features:

  • It can be used to make credentialed requests on the server, as it inherits the cookie and authorization headers for the page request.
  • It can make relative requests on the server (ordinarily, fetch requires a URL with an origin when used in a server context).
  • Internal requests (e.g. for +server.js routes) go directly to the handler function when running on the server, without the overhead of an HTTP call.
  • During server-side rendering, the response will be captured and inlined into the rendered HTML by hooking into the text and json methods of the Response object. Note that headers will not be serialized, unless explicitly included via filterSerializedResponseHeaders
  • During hydration, the response will be read from the HTML, guaranteeing consistency and preventing an additional network request.

You can learn more about making credentialed requests with cookies here

fetch
, setHeaders: (headers: Record<string, string>) => void

If you need to set headers for the response, you can do so using the this method. This is useful if you want the page to be cached, for example:

src/routes/blog/+page
export async function load({ fetch, setHeaders }) {
	const url = `https://cms.example.com/articles.json`;
	const response = await fetch(url);

	setHeaders({
		age: response.headers.get('age'),
		'cache-control': response.headers.get('cache-control')
	});

	return response.json();
}

Setting the same header multiple times (even in separate load functions) is an error — you can only set a given header once.

You cannot add a set-cookie header with setHeaders — use the cookies API in a server-only load function instead.

setHeaders has no effect when a load function runs in the browser.

setHeaders
}) => {
const const url: "https://cms.example.com/products.json"url = `https://cms.example.com/products.json`; const const response: Responseresponse = await fetch: (input: string | URL | globalThis.Request, init?: RequestInit) => Promise<Response> (+1 overload)fetch(const url: "https://cms.example.com/products.json"url); // Headers are only set during SSR, caching the page's HTML // for the same length of time as the underlying data. setHeaders: (headers: Record<string, string>) => void

If you need to set headers for the response, you can do so using the this method. This is useful if you want the page to be cached, for example:

src/routes/blog/+page
export async function load({ fetch, setHeaders }) {
	const url = `https://cms.example.com/articles.json`;
	const response = await fetch(url);

	setHeaders({
		age: response.headers.get('age'),
		'cache-control': response.headers.get('cache-control')
	});

	return response.json();
}

Setting the same header multiple times (even in separate load functions) is an error — you can only set a given header once.

You cannot add a set-cookie header with setHeaders — use the cookies API in a server-only load function instead.

setHeaders has no effect when a load function runs in the browser.

setHeaders
({
age: string | nullage: const response: Responseresponse.Response.headers: Headersheaders.Headers.get(name: string): string | nullget('age'), 'cache-control': const response: Responseresponse.Response.headers: Headersheaders.Headers.get(name: string): string | nullget('cache-control') }); return const response: Responseresponse.Body.json(): Promise<any>json(); };

多次设置相同的 Header(即使在单独的 load 函数中)是一个错误。您只能使用 setHeaders 函数设置一次给定的 Header。您不能使用 setHeaders 添加 set-cookie Header — 请改用 cookies.set(name, value, options)

使用父级数据

有时,load 函数需要访问父级 load 函数的数据,这可以通过 await parent() 来实现。

src/routes/+layout
/** @type {import('./$types').LayoutLoad} */
export function 
function load(): {
    a: number;
}
@type{import('./$types').LayoutLoad}
load
() {
return { a: numbera: 1 }; }
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 { a: numbera: 1 }; };
src/routes/abc/+layout
/** @type {import('./$types').LayoutLoad} */
export async function 
function load({ parent }: {
    parent: any;
}): Promise<{
    b: any;
}>
@type{import('./$types').LayoutLoad}
load
({ parent: anyparent }) {
const { const a: anya } = await parent: anyparent(); return { b: anyb: const a: anya + 1 }; }
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
= async ({ parent: () => Promise<Record<string, any>>

await parent() returns data from parent +layout.js load functions. Implicitly, a missing +layout.js is treated as a ({ data }) => data function, meaning that it will return and forward data from parent +layout.server.js files.

Be careful not to introduce accidental waterfalls when using await parent(). If for example you only want to merge parent data into the returned output, call it after fetching your other data.

parent
}) => {
const { const a: anya } = await parent: () => Promise<Record<string, any>>

await parent() returns data from parent +layout.js load functions. Implicitly, a missing +layout.js is treated as a ({ data }) => data function, meaning that it will return and forward data from parent +layout.server.js files.

Be careful not to introduce accidental waterfalls when using await parent(). If for example you only want to merge parent data into the returned output, call it after fetching your other data.

parent
();
return { b: anyb: const a: anya + 1 }; };
src/routes/abc/+page
/** @type {import('./$types').PageLoad} */
export async function 
function load({ parent }: {
    parent: any;
}): Promise<{
    c: any;
}>
@type{import('./$types').PageLoad}
load
({ parent: anyparent }) {
const { const a: anya, const b: anyb } = await parent: anyparent(); return { c: anyc: const a: anya + const b: anyb }; }
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
= async ({ parent: () => Promise<Record<string, any>>

await parent() returns data from parent +layout.js load functions. Implicitly, a missing +layout.js is treated as a ({ data }) => data function, meaning that it will return and forward data from parent +layout.server.js files.

Be careful not to introduce accidental waterfalls when using await parent(). If for example you only want to merge parent data into the returned output, call it after fetching your other data.

parent
}) => {
const { const a: anya, const b: anyb } = await parent: () => Promise<Record<string, any>>

await parent() returns data from parent +layout.js load functions. Implicitly, a missing +layout.js is treated as a ({ data }) => data function, meaning that it will return and forward data from parent +layout.server.js files.

Be careful not to introduce accidental waterfalls when using await parent(). If for example you only want to merge parent data into the returned output, call it after fetching your other data.

parent
();
return { c: anyc: const a: anya + const b: anyb }; };
src/routes/abc/+page
<script>
	/** @type {{ data: import('./$types').PageData }} */
	let { data } = $props();
</script>

<!-- renders `1 + 2 = 3` -->
<p>{data.a} + {data.b} = {data.c}</p>
<script lang="ts">
	import type { PageData } from './$types';

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

<!-- renders `1 + 2 = 3` -->
<p>{data.a} + {data.b} = {data.c}</p>

请注意,+page.js 中的 load 函数接收来自两个布局 load 函数的合并数据,而不仅仅是直接父级。

+page.server.js+layout.server.js 内部,parent 返回来自父级 +layout.server.js 文件的数据。

+page.js+layout.js 中,它将返回来自父级 +layout.js 文件的数据。但是,如果缺少 +layout.js,则会被视为 ({ data }) => data 函数,这意味着它也将返回来自父级 +layout.server.js 文件的数据,这些数据不会被 +layout.js 文件“遮蔽”。

在使用 await parent() 时,注意不要引入瀑布效应。例如,这里 getData(params) 不依赖于调用 parent() 的结果,因此我们应该先调用它以避免延迟渲染。

+page
/** @type {import('./$types').PageLoad} */
export async function function load(event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').PageLoad}
load
({ params: Record<string, any>

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

params
, parent: () => Promise<Record<string, any>>

await parent() returns data from parent +layout.js load functions. Implicitly, a missing +layout.js is treated as a ({ data }) => data function, meaning that it will return and forward data from parent +layout.server.js files.

Be careful not to introduce accidental waterfalls when using await parent(). If for example you only want to merge parent data into the returned output, call it after fetching your other data.

parent
}) {
const parentData = await parent(); const
const data: {
    meta: any;
}
data
= await
function getData(params: Record<string, string>): Promise<{
    meta: any;
}>
getData
(params: Record<string, any>

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

params
);
const const parentData: Record<string, any>parentData = await parent: () => Promise<Record<string, any>>

await parent() returns data from parent +layout.js load functions. Implicitly, a missing +layout.js is treated as a ({ data }) => data function, meaning that it will return and forward data from parent +layout.server.js files.

Be careful not to introduce accidental waterfalls when using await parent(). If for example you only want to merge parent data into the returned output, call it after fetching your other data.

parent
();
return { ...
const data: {
    meta: any;
}
data
,
meta: anymeta: { ...const parentData: Record<string, any>parentData.meta, ...
const data: {
    meta: any;
}
data
.meta: anymeta }
}; }
import type { type PageLoad = (event: 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: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageLoad = async ({ params: Record<string, any>

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

params
, parent: () => Promise<Record<string, any>>

await parent() returns data from parent +layout.js load functions. Implicitly, a missing +layout.js is treated as a ({ data }) => data function, meaning that it will return and forward data from parent +layout.server.js files.

Be careful not to introduce accidental waterfalls when using await parent(). If for example you only want to merge parent data into the returned output, call it after fetching your other data.

parent
}) => {
const parentData = await parent(); const
const data: {
    meta: any;
}
data
= await
function getData(params: Record<string, string>): Promise<{
    meta: any;
}>
getData
(params: Record<string, any>

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

params
);
const const parentData: Record<string, any>parentData = await parent: () => Promise<Record<string, any>>

await parent() returns data from parent +layout.js load functions. Implicitly, a missing +layout.js is treated as a ({ data }) => data function, meaning that it will return and forward data from parent +layout.server.js files.

Be careful not to introduce accidental waterfalls when using await parent(). If for example you only want to merge parent data into the returned output, call it after fetching your other data.

parent
();
return { ...
const data: {
    meta: any;
}
data
,
meta: anymeta: { ...const parentData: Record<string, any>parentData.meta, ...
const data: {
    meta: any;
}
data
.meta: anymeta }
}; };

错误

如果在 load 期间抛出错误,则将渲染最近的 +error.svelte。对于 预期 错误,请使用 @sveltejs/kit 中的 error 辅助函数来指定 HTTP 状态码和可选的消息。

src/routes/admin/+layout.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').LayoutServerLoad} */ export function function load(event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').LayoutServerLoad}
load
({ locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
}) {
if (!locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
.
App.Locals.user?: {
    name: string;
    isAdmin: boolean;
} | undefined
user
) {
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
(401, 'not logged in');
} if (!locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
.
App.Locals.user?: {
    name: string;
    isAdmin: boolean;
}
user
.isAdmin: booleanisAdmin) {
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
(403, 'not an admin');
} }
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 LayoutServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>LayoutServerLoad } from './$types'; export const const load: LayoutServerLoadload: type LayoutServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>LayoutServerLoad = ({ locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
}) => {
if (!locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
.
App.Locals.user?: {
    name: string;
    isAdmin: boolean;
} | undefined
user
) {
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
(401, 'not logged in');
} if (!locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
.
App.Locals.user?: {
    name: string;
    isAdmin: boolean;
}
user
.isAdmin: booleanisAdmin) {
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
(403, 'not an admin');
} };

调用 error(...) 将抛出异常,从而可以轻松地从辅助函数内部停止执行。

如果抛出 意外 错误,SvelteKit 将调用 handleError 并将其视为 500 内部服务器错误。

在 SvelteKit 1.x 中,您必须自己 throw 错误。

重定向

要重定向用户,请使用 @sveltejs/kit 中的 redirect 辅助函数来指定应将他们重定向到的位置以及 3xx 状态码。与 error(...) 一样,调用 redirect(...) 将抛出异常,从而可以轻松地从辅助函数内部停止执行。

src/routes/user/+layout.server
import { function redirect(status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | ({} & number), location: string | URL): never

Redirect a request. When called during request handling, SvelteKit will return a redirect response. Make sure you’re not catching the thrown redirect, which would prevent SvelteKit from handling it.

@paramstatus The HTTP status code. Must be in the range 300-308.
@paramlocation The location to redirect to.
@throwsRedirect This error instructs SvelteKit to redirect to the specified location.
@throwsError If the provided status is invalid.
redirect
} from '@sveltejs/kit';
/** @type {import('./$types').LayoutServerLoad} */ export function function load(event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').LayoutServerLoad}
load
({ locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
}) {
if (!locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
.
App.Locals.user?: {
    name: string;
} | undefined
user
) {
function redirect(status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | ({} & number), location: string | URL): never

Redirect a request. When called during request handling, SvelteKit will return a redirect response. Make sure you’re not catching the thrown redirect, which would prevent SvelteKit from handling it.

@paramstatus The HTTP status code. Must be in the range 300-308.
@paramlocation The location to redirect to.
@throwsRedirect This error instructs SvelteKit to redirect to the specified location.
@throwsError If the provided status is invalid.
redirect
(307, '/login');
} }
import { function redirect(status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | ({} & number), location: string | URL): never

Redirect a request. When called during request handling, SvelteKit will return a redirect response. Make sure you’re not catching the thrown redirect, which would prevent SvelteKit from handling it.

@paramstatus The HTTP status code. Must be in the range 300-308.
@paramlocation The location to redirect to.
@throwsRedirect This error instructs SvelteKit to redirect to the specified location.
@throwsError If the provided status is invalid.
redirect
} from '@sveltejs/kit';
import type { type LayoutServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>LayoutServerLoad } from './$types'; export const const load: LayoutServerLoadload: type LayoutServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>LayoutServerLoad = ({ locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
}) => {
if (!locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
.
App.Locals.user?: {
    name: string;
} | undefined
user
) {
function redirect(status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | ({} & number), location: string | URL): never

Redirect a request. When called during request handling, SvelteKit will return a redirect response. Make sure you’re not catching the thrown redirect, which would prevent SvelteKit from handling it.

@paramstatus The HTTP status code. Must be in the range 300-308.
@paramlocation The location to redirect to.
@throwsRedirect This error instructs SvelteKit to redirect to the specified location.
@throwsError If the provided status is invalid.
redirect
(307, '/login');
} };

不要在 try {...} 块内使用 redirect(),因为重定向将立即触发 catch 语句。

在浏览器中,您还可以使用 goto(来自 $app.navigation)在 load 函数之外以编程方式导航。

在 SvelteKit 1.x 中,您必须自己 throw redirect

使用 Promise 进行流式传输

当使用服务器端 load 时,Promise 将在解析时流式传输到浏览器。如果您有缓慢的、不重要的数据,这将非常有用,因为您可以在所有数据可用之前开始渲染页面。

src/routes/blog/[slug]/+page.server
/** @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
}) {
return { // make sure the `await` happens at the end, otherwise we // can't start loading comments until we've loaded the post
comments: Promise<{
    content: string;
}>
comments
:
const loadComments: (slug: string) => Promise<{
    content: string;
}>
loadComments
(params: Record<string, any>

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

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

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

params
.slug)
}; }
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
}) => {
return { // make sure the `await` happens at the end, otherwise we // can't start loading comments until we've loaded the post
comments: Promise<{
    content: string;
}>
comments
:
const loadComments: (slug: string) => Promise<{
    content: string;
}>
loadComments
(params: Record<string, any>

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

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

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

params
.slug)
}; };

例如,这对于创建骨架加载状态非常有用。

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

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

{#await data.comments}
	Loading comments...
{:then comments}
	{#each comments as comment}
		<p>{comment.content}</p>
	{/each}
{:catch error}
	<p>error loading comments: {error.message}</p>
{/await}
<script lang="ts">
	import type { PageData } from './$types';

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

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

{#await data.comments}
	Loading comments...
{:then comments}
	{#each comments as comment}
		<p>{comment.content}</p>
	{/each}
{:catch error}
	<p>error loading comments: {error.message}</p>
{/await}

在流式传输数据时,请务必正确处理 Promise 拒绝。更具体地说,如果延迟加载的 Promise 在渲染开始之前失败(此时它会被捕获)并且没有以某种方式处理错误,则服务器可能会因“未处理的 Promise 拒绝”错误而崩溃。当在 load 函数中直接使用 SvelteKit 的 fetch 时,SvelteKit 将为您处理这种情况。对于其他 Promise,只需将一个空操作 catch 附加到 Promise 上即可将其标记为已处理。

src/routes/+page.server
/** @type {import('./$types').PageServerLoad} */
export function 
function load({ fetch }: {
    fetch: any;
}): {
    ok_manual: Promise<never>;
    ok_fetch: any;
    dangerous_unhandled: Promise<never>;
}
@type{import('./$types').PageServerLoad}
load
({ fetch: anyfetch }) {
const const ok_manual: Promise<never>ok_manual = var Promise: PromiseConstructor

Represents the completion of an asynchronous operation

Promise
.PromiseConstructor.reject<never>(reason?: any): Promise<never>

Creates a new rejected promise for the provided reason.

@paramreason The reason the promise was rejected.
@returnsA new rejected Promise.
reject
();
const ok_manual: Promise<never>ok_manual.Promise<never>.catch<void>(onrejected?: ((reason: any) => void | PromiseLike<void>) | null | undefined): Promise<void>

Attaches a callback for only the rejection of the Promise.

@paramonrejected The callback to execute when the Promise is rejected.
@returnsA Promise for the completion of the callback.
catch
(() => {});
return { ok_manual: Promise<never>ok_manual, ok_fetch: anyok_fetch: fetch: anyfetch('/fetch/that/could/fail'), dangerous_unhandled: Promise<never>dangerous_unhandled: var Promise: PromiseConstructor

Represents the completion of an asynchronous operation

Promise
.PromiseConstructor.reject<never>(reason?: any): Promise<never>

Creates a new rejected promise for the provided reason.

@paramreason The reason the promise was rejected.
@returnsA new rejected Promise.
reject
()
}; }
import type { 
type PageServerLoad = (event: Kit.ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
type PageServerLoad = (event: Kit.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: Kit.ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
type PageServerLoad = (event: Kit.ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
PageServerLoad
= ({
fetch: {
    (input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
    (input: string | URL | globalThis.Request, init?: RequestInit): Promise<Response>;
}

fetch is equivalent to the native fetch web API, with a few additional features:

  • It can be used to make credentialed requests on the server, as it inherits the cookie and authorization headers for the page request.
  • It can make relative requests on the server (ordinarily, fetch requires a URL with an origin when used in a server context).
  • Internal requests (e.g. for +server.js routes) go directly to the handler function when running on the server, without the overhead of an HTTP call.
  • During server-side rendering, the response will be captured and inlined into the rendered HTML by hooking into the text and json methods of the Response object. Note that headers will not be serialized, unless explicitly included via filterSerializedResponseHeaders
  • During hydration, the response will be read from the HTML, guaranteeing consistency and preventing an additional network request.

You can learn more about making credentialed requests with cookies here

fetch
}) => {
const const ok_manual: Promise<never>ok_manual = var Promise: PromiseConstructor

Represents the completion of an asynchronous operation

Promise
.PromiseConstructor.reject<never>(reason?: any): Promise<never>

Creates a new rejected promise for the provided reason.

@paramreason The reason the promise was rejected.
@returnsA new rejected Promise.
reject
();
const ok_manual: Promise<never>ok_manual.Promise<never>.catch<void>(onrejected?: ((reason: any) => void | PromiseLike<void>) | null | undefined): Promise<void>

Attaches a callback for only the rejection of the Promise.

@paramonrejected The callback to execute when the Promise is rejected.
@returnsA Promise for the completion of the callback.
catch
(() => {});
return { ok_manual: Promise<never>ok_manual, ok_fetch: Promise<Response>ok_fetch: fetch: (input: string | URL | globalThis.Request, init?: RequestInit) => Promise<Response> (+1 overload)fetch('/fetch/that/could/fail'), dangerous_unhandled: Promise<never>dangerous_unhandled: var Promise: PromiseConstructor

Represents the completion of an asynchronous operation

Promise
.PromiseConstructor.reject<never>(reason?: any): Promise<never>

Creates a new rejected promise for the provided reason.

@paramreason The reason the promise was rejected.
@returnsA new rejected Promise.
reject
()
}; };

在不支持流式传输的平台上(例如 AWS Lambda 或 Firebase),响应将被缓冲。这意味着页面将只在所有 Promise 解析后才会渲染。如果您使用代理(例如 NGINX),请确保它不会缓冲来自代理服务器的响应。

只有在启用 JavaScript 时,流式传输数据才有效。如果您希望页面进行服务器端渲染,则应避免从通用 load 函数返回 Promise,因为这些 Promise **不会**被流式传输 — 相反,当函数在浏览器中重新运行时,Promise 会被重新创建。

一旦响应开始流式传输,就不能更改响应的 Headers 和状态码,因此您不能在流式传输的 Promise 内部 setHeaders 或抛出重定向。

在 SvelteKit 1.x 中,顶层 Promise 会自动等待,只有嵌套的 Promise 会被流式传输。

并行加载

在渲染(或导航到)页面时,SvelteKit 会同时运行所有 load 函数,避免请求的瀑布效应。在客户端导航期间,调用多个服务器端 load 函数的结果会被组合到一个响应中。一旦所有 load 函数都返回,页面就会被渲染。

重新运行 load 函数

SvelteKit 会跟踪每个 load 函数的依赖项,以避免在导航期间不必要地重新运行它。

例如,给定一对如下所示的 load 函数...

src/routes/blog/[slug]/+page.server
import * as module "$lib/server/database"db from '$lib/server/database';

/** @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
}) {
return {
post: {
    title: string;
    content: string;
}
post
: await module "$lib/server/database"db.
function getPost(slug: string): Promise<{
    title: string;
    content: string;
}>
getPost
(params: Record<string, any>

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

params
.slug)
}; }
import * as module "$lib/server/database"db from '$lib/server/database';
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
}) => {
return {
post: {
    title: string;
    content: string;
}
post
: await module "$lib/server/database"db.
function getPost(slug: string): Promise<{
    title: string;
    content: string;
}>
getPost
(params: Record<string, any>

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

params
.slug)
}; };
src/routes/blog/[slug]/+layout.server
import * as module "$lib/server/database"db from '$lib/server/database';

/** @type {import('./$types').LayoutServerLoad} */
export async function function load(event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').LayoutServerLoad}
load
() {
return {
posts: {
    title: string;
    slug: string;
}[]
posts
: await module "$lib/server/database"db.
function getPostSummaries(): Promise<Array<{
    title: string;
    slug: string;
}>>
getPostSummaries
()
}; }
import * as module "$lib/server/database"db from '$lib/server/database';
import type { type LayoutServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>LayoutServerLoad } from './$types';

export const const load: LayoutServerLoadload: type LayoutServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>LayoutServerLoad = async () => {
	return {
		
posts: {
    title: string;
    slug: string;
}[]
posts
: await module "$lib/server/database"db.
function getPostSummaries(): Promise<Array<{
    title: string;
    slug: string;
}>>
getPostSummaries
()
}; };

...如果我们从 /blog/trying-the-raw-meat-diet 导航到 /blog/i-regret-my-choices,则 +page.server.js 中的函数将重新运行,因为 params.slug 已更改。+layout.server.js 中的函数不会重新运行,因为数据仍然有效。换句话说,我们不会第二次调用 db.getPostSummaries()

如果父级 load 函数重新运行,则调用 await parent()load 函数也将重新运行。

依赖项跟踪不适用于 load 函数返回之后 — 例如,在嵌套的 Promise 内部访问 params.x 不会在 params.x 更改时导致函数重新运行。(不用担心,如果您意外地这样做,开发环境中会发出警告。)相反,在 load 函数的主体中访问参数。

搜索参数与 URL 的其余部分独立跟踪。例如,在 load 函数内部访问 event.url.searchParams.get("x") 将在从 ?x=1 导航到 ?x=2 时使该 load 函数重新运行,但在从 ?x=1&y=1 导航到 ?x=1&y=2 时不会重新运行。

取消跟踪依赖项

在极少数情况下,您可能希望从依赖项跟踪机制中排除某些内容。您可以使用提供的 untrack 函数来实现。

src/routes/+page
/** @type {import('./$types').PageLoad} */
export async function 
function load({ untrack, url }: {
    untrack: any;
    url: any;
}): Promise<{
    message: string;
} | undefined>
@type{import('./$types').PageLoad}
load
({ untrack: anyuntrack, url: anyurl }) {
// Untrack url.pathname so that path changes don't trigger a rerun if (untrack: anyuntrack(() => url: anyurl.pathname === '/')) { return { message: stringmessage: 'Welcome!' }; } }
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
= async ({ untrack: <T>(fn: () => T) => T

Use this function to opt out of dependency tracking for everything that is synchronously called within the callback. Example:

src/routes/+page.server
export async function load({ untrack, url }) {
	// Untrack url.pathname so that path changes don't trigger a rerun
	if (untrack(() => url.pathname === '/')) {
		return { message: 'Welcome!' };
	}
}
untrack
, url: URL

The URL of the current page

url
}) => {
// Untrack url.pathname so that path changes don't trigger a rerun if (untrack: <boolean>(fn: () => boolean) => boolean

Use this function to opt out of dependency tracking for everything that is synchronously called within the callback. Example:

src/routes/+page.server
export async function load({ untrack, url }) {
	// Untrack url.pathname so that path changes don't trigger a rerun
	if (untrack(() => url.pathname === '/')) {
		return { message: 'Welcome!' };
	}
}
untrack
(() => url: URL

The URL of the current page

url
.URL.pathname: stringpathname === '/')) {
return { message: stringmessage: 'Welcome!' }; } };

手动失效

您还可以使用 invalidate(url) 重新运行适用于当前页面的 load 函数,该函数会重新运行所有依赖于 urlload 函数,以及 invalidateAll(),该函数会重新运行每个 load 函数。服务器端 load 函数永远不会自动依赖于获取的 url,以避免将机密泄露给客户端。

如果 load 函数调用 fetch(url)depends(url),则它依赖于 url。请注意,url 可以是自定义标识符,以 [a-z]: 开头。

src/routes/random-number/+page
/** @type {import('./$types').PageLoad} */
export async function 
function load({ fetch, depends }: {
    fetch: any;
    depends: any;
}): Promise<{
    number: any;
}>
@type{import('./$types').PageLoad}
load
({ fetch: anyfetch, depends: anydepends }) {
// load reruns when `invalidate('https://api.example.com/random-number')` is called... const const response: anyresponse = await fetch: anyfetch('https://api.example.com/random-number'); // ...or when `invalidate('app:random')` is called depends: anydepends('app:random'); return { number: anynumber: await const response: anyresponse.json() }; }
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
= async ({
fetch: {
    (input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
    (input: string | URL | globalThis.Request, init?: RequestInit): Promise<Response>;
}

fetch is equivalent to the native fetch web API, with a few additional features:

  • It can be used to make credentialed requests on the server, as it inherits the cookie and authorization headers for the page request.
  • It can make relative requests on the server (ordinarily, fetch requires a URL with an origin when used in a server context).
  • Internal requests (e.g. for +server.js routes) go directly to the handler function when running on the server, without the overhead of an HTTP call.
  • During server-side rendering, the response will be captured and inlined into the rendered HTML by hooking into the text and json methods of the Response object. Note that headers will not be serialized, unless explicitly included via filterSerializedResponseHeaders
  • During hydration, the response will be read from the HTML, guaranteeing consistency and preventing an additional network request.

You can learn more about making credentialed requests with cookies here

fetch
, depends: (...deps: Array<`${string}:${string}`>) => void

This function declares that the load function has a dependency on one or more URLs or custom identifiers, which can subsequently be used with invalidate() to cause load to rerun.

Most of the time you won’t need this, as fetch calls depends on your behalf — it’s only necessary if you’re using a custom API client that bypasses fetch.

URLs can be absolute or relative to the page being loaded, and must be encoded.

Custom identifiers have to be prefixed with one or more lowercase letters followed by a colon to conform to the URI specification.

The following example shows how to use depends to register a dependency on a custom identifier, which is invalidated after a button click, making the load function rerun.

src/routes/+page
let count = 0;
export async function load({ depends }) {
	depends('increase:count');

	return { count: count++ };
}
src/routes/+page
&#x3C;script>
	import { invalidate } from '$app/navigation';

	let { data } = $props();

	const increase = async () => {
		await invalidate('increase:count');
	}
&#x3C;/script>

&#x3C;p>{data.count}&#x3C;p>
&#x3C;button on:click={increase}>Increase Count&#x3C;/button>
depends
}) => {
// load reruns when `invalidate('https://api.example.com/random-number')` is called... const const response: Responseresponse = await fetch: (input: string | URL | globalThis.Request, init?: RequestInit) => Promise<Response> (+1 overload)fetch('https://api.example.com/random-number'); // ...or when `invalidate('app:random')` is called depends: (...deps: Array<`${string}:${string}`>) => void

This function declares that the load function has a dependency on one or more URLs or custom identifiers, which can subsequently be used with invalidate() to cause load to rerun.

Most of the time you won’t need this, as fetch calls depends on your behalf — it’s only necessary if you’re using a custom API client that bypasses fetch.

URLs can be absolute or relative to the page being loaded, and must be encoded.

Custom identifiers have to be prefixed with one or more lowercase letters followed by a colon to conform to the URI specification.

The following example shows how to use depends to register a dependency on a custom identifier, which is invalidated after a button click, making the load function rerun.

src/routes/+page
let count = 0;
export async function load({ depends }) {
	depends('increase:count');

	return { count: count++ };
}
src/routes/+page
&#x3C;script>
	import { invalidate } from '$app/navigation';

	let { data } = $props();

	const increase = async () => {
		await invalidate('increase:count');
	}
&#x3C;/script>

&#x3C;p>{data.count}&#x3C;p>
&#x3C;button on:click={increase}>Increase Count&#x3C;/button>
depends
('app:random');
return { number: anynumber: await const response: Responseresponse.Body.json(): Promise<any>json() }; };
src/routes/random-number/+page
<script>
	import { invalidate, invalidateAll } from '$app/navigation';

	/** @type {{ data: import('./$types').PageData }} */
	let { data } = $props();

	function rerunLoadFunction() {
		// any of these will cause the `load` function to rerun
		invalidate('app:random');
		invalidate('https://api.example.com/random-number');
		invalidate(url => url.href.includes('random-number'));
		invalidateAll();
	}
</script>

<p>random number: {data.number}</p>
<button onclick={rerunLoadFunction}>Update random number</button>
<script lang="ts">
	import { invalidate, invalidateAll } from '$app/navigation';
	import type { PageData } from './$types';

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

	function rerunLoadFunction() {
		// any of these will cause the `load` function to rerun
		invalidate('app:random');
		invalidate('https://api.example.com/random-number');
		invalidate(url => url.href.includes('random-number'));
		invalidateAll();
	}
</script>

<p>random number: {data.number}</p>
<button onclick={rerunLoadFunction}>Update random number</button>

何时重新运行 load 函数?

总而言之,load 函数将在以下情况下重新运行:

  • 它引用了 params 的某个属性,并且该属性的值已更改。
  • 它引用了 url 的某个属性(例如 url.pathnameurl.search),并且该属性的值已更改。request.url 中的属性**不会**被跟踪。
  • 它调用了 url.searchParams.get(...)url.searchParams.getAll(...)url.searchParams.has(...),并且相关参数已更改。访问 url.searchParams 的其他属性将与访问 url.search 具有相同的效果。
  • 它调用了 await parent(),并且父级 load 函数重新运行了。
  • load 函数调用了 await parent() 并且正在重新运行,并且父级是服务器端 load 函数。
  • 它通过 fetch(仅限通用 load)或 depends 声明了对特定 URL 的依赖关系,并且该 URL 使用 invalidate(url) 被标记为无效。
  • 所有活动的 load 函数都使用 invalidateAll() 被强制重新运行。

paramsurl 可能会响应 <form> 交互goto 调用或 redirect 而更改。

请注意,重新运行 load 函数将更新相应 +layout.svelte+page.svelte 内部 data 属性;它**不会**导致组件被重新创建。因此,内部状态将被保留。如果这不是您想要的结果,您可以在 afterNavigate 回调内部重置您需要重置的内容,以及/或者将您的组件包装在 {#key ...} 块中。

对身份验证的影响

加载数据的几个功能对身份验证检查具有重要影响。

  • 布局 load 函数不会在每次请求时都运行,例如在客户端在子路由之间导航时。 (何时重新运行 load 函数?)
  • 布局和页面 load 函数会并发运行,除非调用了 await parent()。如果布局 load 抛出错误,页面 load 函数将运行,但客户端将不会收到返回的数据。

有一些可能的策略可以确保在受保护的代码之前进行身份验证检查。

为了防止数据瀑布效应并保留布局 load 缓存:

  • 使用 hooks 在任何 load 函数运行之前保护多个路由。
  • +page.server.js load 函数中直接使用身份验证防护来保护特定路由。

将身份验证防护放在 +layout.server.js 中要求所有子页面在受保护的代码之前调用 await parent()。除非每个子页面都依赖于 await parent() 返回的数据,否则其他选项的性能会更好。

进一步阅读

在 GitHub 上编辑此页面

上一页 下一页