Skip to main content

Context(上下文)

大多数状态是组件级别的状态,其生命周期与组件相同。然而,也存在应用程序范围或页面范围的状态,这也需要进行相应的处理。

处理这种情况最简单的方法是创建全局状态并直接导入它。

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: { /* ... */ } /* ... */ });
App
<script>
	import { myGlobalState } from './state.svelte.js';
	// ...
</script>
<script lang="ts">
	import { myGlobalState } from './state.svelte.js';
	// ...
</script>

这样做有几个缺点:

  • 只有当您的全局状态仅在客户端使用时,它才能安全地工作 - 例如,当您正在构建一个不在服务端渲染任何组件的单页应用时。如果您的状态最终在服务端被管理和更新,它可能会在 sessions 和(或)用户之间共享,从而导致 bug
  • 这可能给人一种误导性的印象,即某个状态是全局的,而实际上它只应该在你的应用程序的某个特定部分使用

为了解决这些缺点,Svelte 提供了一些 context 原语来缓解这些问题。

设置和获取上下文

要将任意对象与当前组件关联,请使用 setContext

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

	setContext('key', value);
</script>

然后,组件的子级(包括插槽内容)可以使用 getContext 访问上下文。

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

	const value = getContext('key');
</script>

setContextgetContext 解决了上述问题:

  • 状态不是全局的,而是限定在组件范围内。这样就可以安全地在服务端渲染组件而不会泄露状态
  • 很明显,状态不是全局的,而是限定在特定的组件树中,因此不能在应用的其他部分使用

setContext / getContext 必须在组件初始化期间调用。

上下文本身不是响应式的。如果你需要上下文中的响应式值,你可以传递一个 $state 对象到上下文中,其属性 将会 是响应式的。

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

	let value = $state({ count: 0 });
	setContext('counter', value);
</script>

<button onclick={() => value.count++}>增加</button>
<script lang="ts">
	import { setContext } from 'svelte';

	let value = $state({ count: 0 });
	setContext('counter', value);
</script>

<button onclick={() => value.count++}>增加</button>
Child
<script>
	import { getContext } from 'svelte';

	const value = getContext('counter');
</script>

<p>计数为 {value.count}</p>
<script lang="ts">
	import { getContext } from 'svelte';

	const value = getContext('counter');
</script>

<p>计数为 {value.count}</p>

要检查给定的 key 是否已在父组件的上下文中设置,可以使用 hasContext

<script>
	import { hasContext } from 'svelte';

	if (hasContext('key')) {
		// 执行某些操作
	}
</script>

您还可以使用 getAllContexts 获取属于最近父组件的整个上下文映射。这在你以编程方式创建组件并想要将现有上下文传递给它时很有用。

<script>
	import { getAllContexts } from 'svelte';

	const contexts = getAllContexts();
</script>

封装上下文交互

上述方法对如何使用它们并没有太多限制。当你的应用规模增长时,将设置和获取上下文封装到函数中并正确地为其添加类型是值得的。

import { function getContext<T>(key: any): T

Retrieves the context that belongs to the closest parent component with the specified key. Must be called during component initialisation.

getContext
, function setContext<T>(key: any, context: T): T

Associates an arbitrary context object with the current component and the specified key and returns that object. The context is then available to children of the component (including slotted content) with getContext.

Like lifecycle functions, this must be called during component initialisation.

setContext
} from 'svelte';
let let userKey: symboluserKey =
var Symbol: SymbolConstructor
(description?: string | number) => symbol

Returns a new unique Symbol value.

@paramdescription Description of the new Symbol object.
Symbol
('user');
export function function setUserContext(user: User): voidsetUserContext(user: Useruser: type User = /*unresolved*/ anyUser) { setContext<User>(key: any, context: User): User

Associates an arbitrary context object with the current component and the specified key and returns that object. The context is then available to children of the component (including slotted content) with getContext.

Like lifecycle functions, this must be called during component initialisation.

setContext
(let userKey: symboluserKey, user: Useruser);
} export function function getUserContext(): UsergetUserContext(): type User = /*unresolved*/ anyUser { return getContext<User>(key: any): User

Retrieves the context that belongs to the closest parent component with the specified key. Must be called during component initialisation.

getContext
(let userKey: symboluserKey) as type User = /*unresolved*/ anyUser;
}

在 GitHub 编辑此页面

上一页 下一页