上下文
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)...
<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:
<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 snippet(demo)的一部分渲染时,这特别有用:
¥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.
除了 setContext 和 getContext,Svelte 还公开了 hasContext 和 getAllContexts 函数。
¥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
作为直接使用 setContext 和 getContext 的替代方案,你可以通过 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:
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:
export const const myGlobalState: {
user: {};
}
myGlobalState = function $state<{
user: {};
}>(initial: {
user: {};
}): {
user: {};
} (+1 overload)
namespace $state
$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!)...
<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.