上下文
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、Array、Objects。
注意事项
- 提供的值将不会在整个渲染树中全局可用,而只能在树中的后代组件中使用。
- 如果在 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>
);
});