上下文
大多數狀態是元件層級的狀態,其生命週期與元件相同。然而,也有區段範圍或應用程式範圍的狀態,也需要以某種方式處理。
最簡單的方法是建立全域狀態並直接匯入。
export const const myGlobalState: {
user: {};
}
myGlobalState = function $state<{
user: {};
}>(initial: {
user: {};
}): {
user: {};
} (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
$state({
user: {}
user: {
/* ... */
}
/* ... */
});
<script>
import { myGlobalState } from './state.svelte';
// ...
</script>
但這有一些缺點
- 只有在您的全域狀態僅在客戶端使用時才能安全運作 - 例如,當您建置一個不在伺服器上渲染任何元件的單頁應用程式時。如果您的狀態最終在伺服器上管理和更新,則可能會在會話和/或使用者之間共享,導致錯誤
- 它可能會給人一種錯誤的印象,認為某些狀態是全域的,但實際上它應該只在您的應用程式的某個部分中使用
為了解決這些缺點,Svelte 提供了一些 context
原始值來緩解這些問題。
設定與取得上下文
若要將任意物件與目前元件關聯,請使用 setContext
。
<script>
import { setContext } from 'svelte';
setContext('key', value);
</script>
然後可以使用 getContext
在元件的子元件(包括插槽內容)中使用此上下文。
<script>
import { getContext } from 'svelte';
const value = getContext('key');
</script>
setContext
和 getContext
解決了上述問題
- 狀態不是全域的,而是限定於元件的作用域。這樣做可以在伺服器上安全地渲染您的元件,而不會洩漏狀態
- 很明顯,狀態不是全域的,而是限定於特定元件樹狀結構的作用域,因此不能在應用程式的其他部分中使用
setContext
/getContext
必須在元件初始化期間呼叫。
上下文本質上不是反應式的。如果您的上下文需要反應式的值,則可以將 $state
物件傳遞到上下文中,其屬性將具有反應性。
<script>
import { setContext } from 'svelte';
let value = $state({ count: 0 });
setContext('counter', value);
</script>
<button onclick={() => value.count++}>increment</button>
<script>
import { getContext } from 'svelte';
const value = getContext('counter');
</script>
<p>Count is {value.count}</p>
若要檢查給定的 key
是否已在父元件的上下文中設定,請使用 hasContext
。
<script>
import { hasContext } from 'svelte';
if (hasContext('key')) {
// do something
}
</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: symbol
userKey = var Symbol: SymbolConstructor
(description?: string | number) => symbol
Returns a new unique Symbol value.
Symbol('user');
export function function setUserContext(user: User): void
setUserContext(user: User
user: type User = /*unresolved*/ any
User) {
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: symbol
userKey, user: User
user);
}
export function function getUserContext(): User
getUserContext(): type User = /*unresolved*/ any
User {
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: symbol
userKey) as type User = /*unresolved*/ any
User;
}