重新导出加载器
routeAction$
和 routeLoader$
通常在路由边界文件中声明,例如 routesDir 目录中的 layout.tsx、index.tsx 和 plugin.tsx 这里有文档.
有时您可能希望在路由边界之外声明它们。当您想要创建可重用逻辑或库时,这可能很有用。在这种情况下,必须从路由边界内重新导出此函数,否则它将无法运行或抛出异常。
解决方案
您可以在自定义路径中定义 routeAction$
和 routeLoader$
,并在 layout.tsx、index.tsx 和 plugin.tsx 文件中重新导出它们。
可重用逻辑示例
假设我们有一个 routeLoader$
用于检查用户是否已登录。将相同的代码复制粘贴到我们代码的许多部分以使其工作是没有意义的。根据最佳实践,理想的方法是集中逻辑。在本示例中,我们在一个集中文件中声明 routeAction$
和 routeLoader$
,以便我们可以在我们的文件中重用它。
使用 ./shared/loaders.ts
的示例
import { routeAction$, routeLoader$ } from '@builder.io/qwik-city';
export const useCommonRouteAction = routeAction$(async () => {
// ...
return { success: true, data: ['Qwik', 'Partytown'] };
});
export const useCommonRouteLoader = routeLoader$(async () => {
// ...
return ['Mitosis', 'Builder.io'];
});
现在,您可以在类似 ./src/routes/index.tsx
的路径中使用您的通用 routeAction$
和 routeLoader$
。
import { component$ } from '@builder.io/qwik';
import { Form } from '@builder.io/qwik-city';
import { useCommonRouteAction, useCommonRouteLoader } from './shared/loaders';
// As mentioned, here we are re-exporting them
export { useCommonRouteAction, useCommonRouteLoader } from './shared/loaders';
export default component$(() => {
const commonRouteAction = useCommonRouteAction();
const commonRouteLoader = useCommonRouteLoader();
return (
<div class="flex justify-around text-xl">
<Form action={commonRouteAction}>
<div class="mb-2">CommonRouteAction</div>
<div class="mb-4">response:</div>
<div class="text-lg font-bold mb-4">
{commonRouteAction.value?.data.join(' ') || ''}
</div>
<button type="submit">Submit</button>
</Form>
<div>
<div class="mb-2">CommonRouteLoader</div>
<div class="mb-4">response:</div>
<div class="text-lg font-bold mb-4">{commonRouteLoader.value.join(' ')}</div>
</div>
</div>
);
});
第三方库示例
我们可能需要集成第三方库,而我们无法控制它的工作方式。例如,考虑将支付方式集成到我们的应用程序中。我们提供了一个要集成到页面的组件,但我们无法控制该组件内部发生的事情。在这里,如果该库需要 routeAction$
或 routeLoader$
,我们必须重新导出它们以允许我们的库正常运行。
这是我们的代码
import { component$ } from '@builder.io/qwik';
import { ThirdPartyPaymentComponent } from './third-party-library';
// As mentioned, here we are re-exporting the third-party loader
export { useThirdPartyPaymentLoader } from './third-party-library';
export default component$(() => {
return (
<section>
<ThirdPartyPaymentComponent />
</section>
);
});
这是库代码
import { component$ } from '@builder.io/qwik';
import { routeLoader$ } from '@builder.io/qwik-city';
export const useThirdPartyPaymentLoader = routeLoader$(() => {
return { name: 'John Doe' };
});
export const ThirdPartyPaymentComponent = component$(() => {
const thirdPartyPaymentLoader = useThirdPartyPaymentLoader();
return (
<div
class={[
'w-96 h-56 m-auto rounded-xl relative text-white font-bold shadow-2xl',
'transition-transform transform hover:scale-110 bg-gray-600',
]}
>
<div class="w-full px-8 absolute top-8">
<div class="flex justify-between">
<div class="">
<p>Name</p>
<p class="tracking-widest">{thirdPartyPaymentLoader.value.name}</p>
</div>
<img class="w-12 h-12" src="/logos/qwik-logo.svg" />
</div>
<div class="pt-1">
<p class="font-medium">Card Number</p>
<p class="tracking-wider">4642 3489 9867 7632</p>
</div>
<div class="pt-6 pr-6">
<div class="flex justify-between text-xs">
<div>
<p class="font-medium">Valid</p>
<p class="tracking-wider">11/15</p>
</div>
<div>
<p class="font-medium">Expiry</p>
<p class="tracking-wider">03/25</p>
</div>
<div>
<p class="font-medium">CVV</p>
<p class="tracking-wider">···</p>
</div>
</div>
</div>
</div>
</div>
);
});