上下文
Qwik 提供了一个上下文 API,它解决了道具传递的问题,并且与 React 的函数式 useContext()
非常相似。事实上,Qwik 的上下文 API 是传递数据到不同组件的最有效方式,它减少了开销,生成了更少的代码,并允许 Qwik 更有效地 摇树 未使用的數據。
Qwik 的上下文 API 由 3 个方法组成,可以从 @builder.io/qwik
导入
createContextId(contextName: string): ContextId
useContextProvider(ctx: ContextId, value: VALUE): void
useContext(ctx: ContextId): VALUE
import { type Signal, component$, useSignal } from '@builder.io/qwik';
import {
useContext,
useContextProvider,
createContextId,
} from '@builder.io/qwik';
export const ThemeContext = createContextId<Signal<string>>(
'docs.theme-context'
);
export default component$(() => {
const theme = useSignal('dark');
useContextProvider(ThemeContext, theme);
return (
<>
<button
onClick$={() =>
(theme.value = theme.value == 'dark' ? 'light' : 'dark')
}
>
Flip
</button>
<Child />
</>
);
});
const Child = component$(() => {
const theme = useContext(ThemeContext);
return <div>Theme is {theme.value}</div>;
});
在上面的示例中,创建了一个名为 docs.theme-context
的 ContextId
,并用于向 default
组件提供 useSignal
。Child
组件使用 useContext
方法获取 useSignal
并渲染其值。
createContextId()
此方法用于创建一个新的 ContextId
。
export interface GenericType {
...
}
export const QwikCityContext = createContextId<GenericType>(name: string): ContextId<GenericType>;
参数
name
: 是一个唯一的字符串,作为上下文标识符提供给createContextId
。这将避免在存在多个上下文时发生冲突。建议使用诸如io.builder.qwik.city
之类的命名约定。
返回值
请注意,createContextId()
返回的值不包含任何状态,它是一个不可变的 ID 对象,即 { id: 'io.builder.qwik.city' }
。它仅用于描述上下文的名称和类型,就像地址或标识符一样。由于它不包含任何状态,因此可以将其初始化为单例并从共享模块导出。
useContextProvider()
此方法用于使用 ContextId
作为上下文的关键标识符,为特定组件及其后代创建上下文。
src/components/Parent.tsx
import { component$, useStore, useContextProvider } from '@builder.io/qwik';
export const Parent = component$(() => {
const qwikCityObject = useStore<GenericType>({
...
});
useContextProvider(QwikCityContext, qwikCityObject);
useContextProvider(PlainArrayContext, [1, 2, 3])
useContextProvider(AppNameContext, "My Qwik App")
return (
<Children />
);
});
参数
-
ContextId
: 必须提供先前创建的上下文,作为要作为第二个参数提供的数据的标识符。 -
data
: 你可以提供任何数据类型,例如 Qwik 的 useSignal、useStore、数组或对象。
注意事项
- 提供的 value 不会在整个渲染树中全局可用,而只会对树中的后代组件可用。
- 如果在服务器端渲染 (SSR) 期间未使用上下文,则不会对其进行序列化。如果你需要在客户端上使用上下文,即使在 SSR 期间未使用它,也应该在父组件中调用
useContext()
。这将强制对其进行序列化。
useContext()
此方法用于获取由父组件 提供 的 Context
的值。
src/components/Children.tsx
import { component$, useContext } from '@builder.io/qwik';
export const Children = component$(() => {
const qwikCityObject = useContext(QwikCityContext);
const plainArray = useContext(PlainArrayContext);
const appName = useContext(AppNameContext);
return (
<div>Child components can use any of the provided values, such as {appName}</div>
);
});