乐闻世界logo
搜索文章和话题

Qwik City 的核心功能有哪些?

2月21日 15:37

Qwik City 是 Qwik 的全栈框架,提供了完整的路由、数据获取和服务端功能。以下是 Qwik City 的核心概念和使用方法:

1. Qwik City 简介

Qwik City 构建在 Qwik 之上,提供了:

  • 基于文件系统的路由
  • 服务端数据加载
  • 表单处理和验证
  • 中间件支持
  • SEO 优化
  • 国际化支持

2. 路由系统

文件系统路由

Qwik City 使用基于文件系统的路由,文件结构直接映射到 URL:

shell
src/ ├── routes/ │ ├── index.tsx -> / │ ├── about/ │ │ └── index.tsx -> /about │ ├── products/ │ │ ├── index.tsx -> /products │ │ └── [id]/ │ │ └── index.tsx -> /products/:id │ └── layout.tsx -> 全局布局

动态路由

tsx
// routes/products/[id]/index.tsx import { component$ } from '@builder.io/qwik'; import { routeLoader$ } from '@builder.io/qwik-city'; import { useLocation } from '@builder.io/qwik-city'; export const useProductData = routeLoader$(async ({ params, url, env }) => { const response = await fetch(`https://api.example.com/products/${params.id}`); return response.json(); }); export default component$(() => { const product = useProductData(); const location = useLocation(); return ( <div> <h1>{product.value.name}</h1> <p>{product.value.description}</p> <p>Price: ${product.value.price}</p> </div> ); });

嵌套路由

tsx
// routes/layout.tsx import { component$, Slot } from '@builder.io/qwik'; export default component$(() => { return ( <div> <header>Header</header> <main> <Slot /> </main> <footer>Footer</footer> </div> ); });

3. 数据加载

routeLoader$ - 服务端数据加载

tsx
import { routeLoader$ } from '@builder.io/qwik-city'; export const useUserData = routeLoader$(async ({ params, url, env, requestEvent }) => { // 访问请求参数 const userId = params.id; // 访问 URL 查询参数 const searchParams = url.searchParams; const page = searchParams.get('page'); // 访问环境变量 const apiKey = env.get('API_KEY'); // 访问请求事件 const cookie = requestEvent.cookie.get('session'); const response = await fetch(`https://api.example.com/users/${userId}`); return response.json(); });

clientLoader$ - 客户端数据加载

tsx
import { clientLoader$ } from '@builder.io/qwik-city'; export const useClientData = clientLoader$(async ({ params, navigate }) => { // 客户端数据获取 const response = await fetch(`/api/data/${params.id}`); return response.json(); });

useResource$ - 组件级数据加载

tsx
import { component$, useResource$ } from '@builder.io/qwik'; export const UserList = component$(() => { const users = useResource$(({ track, cleanup }) => { // 追踪依赖 track(() => /* 依赖项 */); // 清理函数 cleanup(() => { // 清理逻辑 }); return fetch('https://api.example.com/users'); }); return ( <div> {users.value ? ( <ul> {users.value.map(user => <li key={user.id}>{user.name}</li>)} </ul> ) : ( <p>Loading...</p> )} </div> ); });

4. 表单处理

action$ - 服务端表单处理

tsx
import { action$, zod$, z } from '@builder.io/qwik-city'; import { component$, Form } from '@builder.io/qwik-city'; // 定义表单验证 export const useContactForm = action$(async (data, { requestEvent }) => { // 服务端处理逻辑 const { name, email, message } = data; // 发送邮件 await sendEmail({ name, email, message }); return { success: true }; }, zod$({ name: z.string().min(2), email: z.string().email(), message: z.string().min(10) })); export default component$(() => { const action = useContactForm(); return ( <Form action={action}> <input name="name" placeholder="Name" /> <input name="email" type="email" placeholder="Email" /> <textarea name="message" placeholder="Message"></textarea> <button type="submit">Submit</button> {action.value?.success && <p>Message sent!</p>} </Form> ); });

clientAction$ - 客户端表单处理

tsx
import { clientAction$ } from '@builder.io/qwik-city'; export const useClientAction = clientAction$(async (data) => { // 客户端处理逻辑 console.log('Client action:', data); return { success: true }; });

5. 中间件

请求中间件

tsx
// routes/middleware.ts import { middleware$ } from '@builder.io/qwik-city'; export const onRequest = middleware$(async ({ requestEvent, next }) => { // 请求前处理 const url = requestEvent.url; const cookie = requestEvent.cookie.get('session'); if (!cookie && url.pathname !== '/login') { throw requestEvent.redirect(302, '/login'); } return next(); }); export const onResponse = middleware$(async ({ requestEvent, next }) => { // 响应后处理 const response = await next(); // 添加响应头 response.headers.set('X-Custom-Header', 'value'); return response; });

6. SEO 优化

元数据设置

tsx
import { component$ } from '@builder.io/qwik'; import { routeLoader$, useDocumentHead, useLocation } from '@builder.io/qwik-city'; export const useProductData = routeLoader$(async ({ params }) => { const response = await fetch(`https://api.example.com/products/${params.id}`); return response.json(); }); export default component$(() => { const product = useProductData(); return <div>{product.value.name}</div>; }); export const head = useDocumentHead$(({ resolveValue }) => { const product = resolveValue(useProductData); return { title: product.name, meta: [ { name: 'description', content: product.description }, { property: 'og:title', content: product.name }, { property: 'og:description', content: product.description }, { property: 'og:image', content: product.image } ] }; });

7. 国际化

i18n 配置

tsx
// src/entry.ssr.tsx import { renderToStream } from '@builder.io/qwik/server'; import { Root } from './root'; import { I18nProvider } from 'qwik-speak'; export default function (opts) { return renderToStream(<Root />, { ...opts, containerAttributes: { lang: opts.lang } }); }

使用翻译

tsx
import { component$ } from '@builder.io/qwik'; import { useSpeak } from 'qwik-speak'; export const MyComponent = component$(() => { const { t } = useSpeak(); return ( <div> <h1>{t('welcome.title')}</h1> <p>{t('welcome.description')}</p> </div> ); });

8. 最佳实践

1. 合理使用 routeLoader$ 和 useResource$

  • routeLoader$:用于页面级数据,在服务器执行
  • useResource$:用于组件级数据,可以动态重新获取

2. 错误处理

tsx
export const useData = routeLoader$(async ({ params }) => { try { const response = await fetch(`https://api.example.com/data/${params.id}`); if (!response.ok) { throw new Error('Failed to fetch data'); } return response.json(); } catch (error) { throw requestEvent.redirect(302, '/error'); } });

3. 缓存策略

tsx
export const useCachedData = routeLoader$(async ({ requestEvent }) => { const cacheKey = 'data'; const cached = requestEvent.sharedMap.get(cacheKey); if (cached) { return cached; } const data = await fetchData(); requestEvent.sharedMap.set(cacheKey, data); return data; });

总结:Qwik City 提供了完整的全栈开发体验,通过路由、数据加载、表单处理等功能,开发者可以快速构建高性能的 Web 应用程序。

标签:Qwik