Qwik 提供了多种状态管理方式,每种方式都有其特定的使用场景和优势:
1. useSignal
useSignal 是 Qwik 中最简单的状态管理方式,适用于管理原始值(如数字、字符串、布尔值)。
特点
- 轻量级,性能最优
- 只能存储单个值
- 通过
.value访问和修改值 - 自动触发细粒度更新
使用示例
tsximport { component$, useSignal } from '@builder.io/qwik'; export const Counter = component$(() => { const count = useSignal(0); return ( <div> <p>Count: {count.value}</p> <button onClick$={() => count.value++}>Increment</button> <button onClick$={() => count.value--}>Decrement</button> </div> ); });
2. useStore
useStore 用于管理复杂对象状态,可以存储嵌套对象和数组。
特点
- 可以存储复杂对象和数组
- 支持深层嵌套
- 自动追踪对象属性的变化
- 细粒度更新,只更新变化的属性
使用示例
tsximport { component$, useStore } from '@builder.io/qwik'; export const TodoList = component$(() => { const todos = useStore({ items: [ { id: 1, text: 'Learn Qwik', completed: false }, { id: 2, text: 'Build app', completed: false } ], filter: 'all' }); const addTodo$ = () => { todos.items.push({ id: todos.items.length + 1, text: 'New todo', completed: false }); }; return ( <div> <ul> {todos.items.map(item => ( <li key={item.id}> {item.text} </li> ))} </ul> <button onClick$={addTodo$}>Add Todo</button> </div> ); });
3. useComputed
useComputed 用于创建派生状态,基于其他状态计算得出。
特点
- 自动缓存计算结果
- 只在依赖项变化时重新计算
- 适合处理复杂计算逻辑
使用示例
tsximport { component$, useSignal, useComputed } from '@builder.io/qwik'; export const PriceCalculator = component$(() => { const price = useSignal(100); const tax = useSignal(0.1); const totalPrice = useComputed$(() => { return price.value * (1 + tax.value); }); return ( <div> <p>Price: ${price.value}</p> <p>Tax: {tax.value * 100}%</p> <p>Total: ${totalPrice.value.toFixed(2)}</p> </div> ); });
4. useContext
useContext 用于跨组件共享状态,类似于 React 的 Context API。
特点
- 避免通过多层组件传递 props
- 适合全局状态管理
- 可以在组件树的任何位置访问
使用示例
tsximport { component$, createContext, useContext } from '@builder.io/qwik'; const UserContext = createContext<{ name: string; email: string }>({ name: '', email: '' }); export const UserProvider = component$(() => { const user = { name: 'John Doe', email: 'john@example.com' }; return ( <UserContext.Provider value={user}> <UserProfile /> </UserContext.Provider> ); }); export const UserProfile = component$(() => { const user = useContext(UserContext); return ( <div> <h1>{user.name}</h1> <p>{user.email}</p> </div> ); });
5. useResource
useResource 用于管理异步数据和加载状态。
特点
- 处理异步数据获取
- 自动管理加载状态
- 支持错误处理
- 可以重新获取数据
使用示例
tsximport { component$, useResource, useSignal } from '@builder.io/qwik'; import { routeLoader$ } from '@builder.io/qwik-city'; export const useUserData = routeLoader$(async () => { const response = await fetch('https://api.example.com/users'); return response.json(); }); export const UserList = component$(() => { const users = useResource$(({ track }) => { track(() => /* 依赖项 */); return fetchUsers(); }); return ( <div> {users.value ? ( <ul> {users.value.map(user => ( <li key={user.id}>{user.name}</li> ))} </ul> ) : ( <p>Loading...</p> )} </div> ); });
6. 状态管理最佳实践
选择合适的状态管理方式
- 简单值:使用
useSignal - 复杂对象:使用
useStore - 派生状态:使用
useComputed - 跨组件共享:使用
useContext - 异步数据:使用
useResource
避免不必要的重新渲染
- Qwik 自动处理细粒度更新,不需要手动优化
- 避免在渲染函数中创建新对象
- 使用
useComputed缓存计算结果
状态序列化
- Qwik 会自动序列化状态到 HTML
- 确保状态对象是可序列化的
- 避免存储函数或不可序列化的对象
总结:Qwik 的状态管理系统设计简洁而强大,通过不同的 hook 提供了灵活的状态管理方式。编译器自动处理状态序列化和细粒度更新,使开发者能够专注于业务逻辑而无需担心性能问题。