传递闭包
为了让 Qwik 能够独立地恢复和渲染页面上的每个组件,道具必须是可序列化的。如果我们希望将回调传递给子组件,就会出现问题。回调是函数,函数本身不可直接序列化,但可以通过 $() 将其转换为 QRL 来进行序列化。
QRL
跨可序列化边界的函数传递必须通过 QRL 完成。QRL 是函数的序列化形式。(请参阅高级部分中的 QRL。)
Qwik 提供了以 $ 结尾的便捷 API - 它们等效于直接调用 $()。这两行代码是等效的
- 内联:
useTask$(() => {...}/> - 显式:
const callbackQrl = $(() => {...}); useTaskQrl(callbackQrl)
大多数情况下,我们使用第一种形式,因为它允许我们将回调直接内联到 API 中。但在某些情况下,需要使用第二种形式,以便将函数声明的位置与使用位置分开。
声明回调道具
组件可以通过以下方式在道具中声明回调:
- 以
$结尾的属性(如goodbye$) - 属性的类型为
QRL<T>,其中T是 QRL 指向的延迟引用类型(函数签名)。
interface MyComponentProps {
goodbye$: QRL<() => void>;
hello$: QRL<() => void>;
}
export const MyComponent = component$((props: MyComponentProps) => { ... });这允许 <MyComponent> 的用户使用 goodbye$ 形式,如下所示
<MyComponent goodbye$={goodbyeQrl} hello$={() => {...}} />使用回调道具
请注意,<MyComponent> 组件接收一个回调函数。
将 props.goodbye$ 作为引用传递给 <button>
<button onClick$={props.goodbye$}>good bye</button>为 <button> 创建一个新的回调,并在内部调用回调 QRL。
<button
onClick$={async () => {
await props.hello$?.invoke('World');
}}
>
hello
</button>这种形式允许 <button> 使用自定义参数调用回调。请注意,调用需要 async 和 await,因为 QRL 是延迟加载的。