状态的分层设计
- 基础层状态
- 用户认证状态:记录用户是否登录、用户ID等信息。这是几乎所有模块都可能依赖的基础信息,例如购物车管理和订单流程在操作前需确认用户身份。可以使用一个简单的对象存储,如
{ isLoggedIn: boolean, userId: string | null }
。
- 全局配置状态:如网站的基本设置,如货币单位、默认展示语言等。这些信息在商品浏览、订单流程等模块都可能用到。
- 模块相关状态
- 商品浏览模块:
- 商品列表状态:存储当前展示的商品列表数据,包括商品的基本信息(名称、价格、图片等)。可以根据不同的分类、搜索条件等进行缓存。例如,使用
{ category: string, products: Product[] }
的结构,其中Product
是自定义的商品类型接口。
- 商品详情状态:记录用户查看的具体商品的详细信息,如规格、库存等。
- 购物车管理模块:
- 购物车商品列表状态:存储购物车中所有商品的信息,包括商品数量、选中状态等。结构可以是
{ items: CartItem[], totalPrice: number }
,其中CartItem
包含商品ID、商品信息、数量等。
- 购物车操作状态:如是否正在加载购物车数据、添加或删除商品的操作结果等。
- 订单流程模块:
- 订单信息状态:包括收货地址、联系方式、订单中商品明细、总价等信息。
- 订单状态:如待支付、已支付、已发货等。
- 用户个性化推荐模块:
- 用户偏好状态:记录用户的浏览历史、收藏商品等信息,用于生成个性化推荐。可以使用数组或对象来存储,如
{ viewedProducts: string[], favoriteProducts: string[] }
。
- 推荐商品列表状态:根据用户偏好生成的推荐商品列表数据。
数据流动模式
- 单向数据流:采用单向数据流模式可以使状态管理更可预测。例如,用户在商品浏览模块点击“加入购物车”按钮,这一用户操作触发一个action,该action会更新购物车管理模块的状态(如添加商品到购物车列表)。购物车状态的更新会通过视图绑定机制反映到UI上。
- 事件驱动:各个模块之间通过事件进行通信。比如,当购物车中的商品数量发生变化时,触发一个“购物车更新”事件,订单流程模块监听该事件,根据购物车的新状态更新订单总价等相关信息。
- 异步数据获取与更新:在商品浏览模块获取商品列表数据或在用户个性化推荐模块获取推荐商品列表时,可能需要异步操作。使用
async/await
或Promise来处理异步数据获取。例如,在获取商品列表时:
async function fetchProducts(category: string) {
const response = await fetch(`/api/products?category=${category}`);
const data = await response.json();
// 更新商品列表状态
setProductList({ category, products: data });
}
与其他Qwik特性的协同
- 与路由的协同
- 基于路由的状态更新:不同的路由对应不同的页面模块,当路由发生变化时,相应模块的状态可能需要更新。例如,用户从商品列表页导航到商品详情页,需要根据路由参数(商品ID)更新商品详情状态。可以在路由变化的钩子函数中进行状态更新操作。
- 保护路由:依赖用户认证状态来保护某些路由,如订单流程页面只有在用户登录后才能访问。可以在路由配置中添加权限验证逻辑,检查用户认证状态。
- 与组件交互的协同
- 父子组件通信:父组件可以将全局状态中的相关部分作为props传递给子组件。例如,购物车管理模块的父组件将购物车商品列表状态传递给展示购物车商品的子组件,子组件通过props读取数据并展示。子组件可以通过触发事件通知父组件进行状态更新,如子组件中的“删除商品”按钮点击事件通知父组件更新购物车商品列表状态。
- 跨组件状态共享:对于一些需要跨多个组件共享的状态,可以通过上下文(Context)来实现。例如,全局的用户认证状态可以通过Qwik的上下文机制在整个应用的组件树中共享,避免在组件层级中层层传递props。