传递闭包

为了让 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> 使用自定义参数调用回调。请注意,调用需要 asyncawait,因为 QRL 是延迟加载的。

编辑教程