Skip to main content

上下文

Context 允许组件访问父组件拥有的值,而无需将它们作为 props 传递下去(可能通过多层中间组件,称为 ‘prop-drilling’)。父组件使用 setContext(key, value) 设置上下文……

¥Context allows components to access values owned by parent components without passing them down as props (potentially through many layers of intermediate components, known as ‘prop-drilling’). The parent component sets context with setContext(key, value)...

Parent
<script>
	import { setContext } from 'svelte';

	setContext('my-context', 'hello from Parent.svelte');
</script>
<script lang="ts">
	import { setContext } from 'svelte';

	setContext('my-context', 'hello from Parent.svelte');
</script>

...并且子进程使用 getContext 检索它:

¥...and the child retrieves it with getContext:

Child
<script>
	import { getContext } from 'svelte';

	const message = getContext('my-context');
</script>

<h1>{message}, inside Child.svelte</h1>
<script lang="ts">
	import { getContext } from 'svelte';

	const message = getContext('my-context');
</script>

<h1>{message}, inside Child.svelte</h1>

Parent.svelte 不直接了解 Child.svelte,而是将其作为 children snippetdemo)的一部分渲染时,这特别有用:

¥This is particularly useful when Parent.svelte is not directly aware of Child.svelte, but instead renders it as part of a children snippet (demo):

<Parent>
	<Child />
</Parent>

键(上例中的 'my-context')和上下文本身可以是任何 JavaScript 值。

¥The key ('my-context', in the example above) and the context itself can be any JavaScript value.

除了 setContextgetContext,Svelte 还公开了 hasContextgetAllContexts 函数。

¥In addition to setContext and getContext, Svelte exposes hasContext and getAllContexts functions.

使用带状态的上下文(Using context with state)

¥Using context with state

你可以将反应状态存储在上下文 (demo) 中...

¥You can store reactive state in context (demo)...

<script>
	import { setContext } from 'svelte';
	import Child from './Child.svelte';

	let counter = $state({
		count: 0
	});

	setContext('counter', counter);
</script>

<button onclick={() => counter.count += 1}>
	increment
</button>

<Child />
<Child />
<Child />

...但请注意,如果你重新分配 counter 而不是更新它,你将 ‘断开链接’ — 换句话说,而不是这样...

¥...though note that if you reassign counter instead of updating it, you will ‘break the link’ — in other words instead of this...

<button onclick={() => counter = { count: 0 }}>
	reset
</button>

...你必须这样做:

¥...you must do this:

<button onclick={() => counter.count = 0}>
	reset
</button>

如果你做错了,Svelte 会警告你。

¥Svelte will warn you if you get it wrong.

类型安全上下文(Type-safe context)

¥Type-safe context

作为直接使用 setContextgetContext 的替代方案,你可以通过 createContext 使用它们。这为你提供了类型安全性,并且无需使用键:

¥As an alternative to using setContext and getContext directly, you can use them via createContext. This gives you type safety and makes it unnecessary to use a key:

context
import { function createContext<T>(): [() => T, (context: T) => T]

Returns a [get, set] pair of functions for working with context in a type-safe way.

createContext
} from 'svelte';
export const [const getUserContext: () => UsergetUserContext, const setUserContext: (context: User) => UsersetUserContext] = createContext<User>(): [() => User, (context: User) => User]

Returns a [get, set] pair of functions for working with context in a type-safe way.

createContext
<User>();

替换全局状态(Replacing global state)

¥Replacing global state

当你拥有由许多不同组件共享的状态时,你可能会倾向于将其放在自己的模块中,并在需要的地方导入它:

¥When you have state shared by many different components, you might be tempted to put it in its own module and just import it wherever it’s needed:

state.svelte
export const 
const myGlobalState: {
    user: {};
}
myGlobalState
=
function $state<{
    user: {};
}>(initial: {
    user: {};
}): {
    user: {};
} (+1 overload)
namespace $state

Declares reactive state.

Example:

let count = $state(0);

https://svelte.dev/docs/svelte/$state

@paraminitial The initial value
$state
({
user: {}user: { // ... } // ... });

在许多情况下,这完全没问题,但存在风险:如果你在服务器端渲染期间改变状态(不鼓励这样做,但完全可能!)...

¥In many cases this is perfectly fine, but there is a risk: if you mutate the state during server-side rendering (which is discouraged, but entirely possible!)...

App
<script>
	import { myGlobalState } from './state.svelte.js';

	let { data } = $props();

	if (data.user) {
		myGlobalState.user = data.user;
	}
</script>
<script lang="ts">
	import { myGlobalState } from './state.svelte.js';

	let { data } = $props();

	if (data.user) {
		myGlobalState.user = data.user;
	}
</script>

...然后下一个用户可以访问数据。Context 解决了这个问题,因为它不会在请求之间共享。

¥...then the data may be accessible by the next user. Context solves this problem because it is not shared between requests.

上一页 下一页