Vue 中全局 Store 的隐藏成本(以及何时仍然值得使用)
发布: (2026年1月12日 GMT+8 14:53)
5 min read
原文: Dev.to
Source: Dev.to
为什么全局 Store 看起来很有吸引力
- 状态的集中位置 – 单一的真实来源。
- 出色的 DevTools 集成 – 便于检查和时间旅行调试。
- 类型安全 – 尤其在使用 TypeScript 时。
- 简洁的 API – actions 和 getters 使用起来直观。
Pinia 的常见误用
反模式:存放本地或临时状态
一个非常常见的错误是把本应属于单个组件或视图的状态放进 Pinia store,只因为 store 随手可用。
典型示例
- 模态框的打开/关闭状态
- 表单输入值
- 页面特定的过滤条件
- 临时的加载标记
后果
- Store 膨胀 – 累积了无关的状态片段。
- 所有权不明确 – 难以判断哪段数据“归属”哪个组件。
- 间接层次增加 – 组件必须通过 store 处理本应本地的事务。
- 重构更困难 – 改动会在 store 中蔓延,影响无关的应用部分。
如果某段状态只属于单个组件树或路由,保持本地状态往往更简单、更健康。
依赖蔓延
隐式依赖
每当组件导入一个 store 时,就产生了对以下内容的隐式依赖:
- Store 的结构
- 它的内部逻辑
- 副作用(例如 API 调用)
- 它的生命周期
长期影响
- 组件的可复用性下降。
- 测试需要更多的 mock。
- 对某个 store 的改动可能意外影响许多不相关的组件。
最初的便利会慢慢演变成架构重力,把无关的关注点拉进同一个全局层。
全局响应式的性能影响
响应式开销
全局 store 默认是响应式的,这意味着:
- 任意响应式属性都可能触发更新。
- 使用该 store 的任何组件都会参与其依赖图。
何时会成为负担
以下情况会导致问题:
- 将大型对象存放在全局。
- Store 深度响应式但并非必要。
- 组件订阅的状态多于实际使用的部分。
这些情形可能导致:
- 不必要的重新渲染。
- 计算属性的昂贵重新计算。
- 隐蔽的性能回退。
虽然 shallowRef 等工具或拆分 store 能缓解问题,但最佳的优化往往是根本不把状态全局化。
全局 Store 仍然值得使用的场景
理想使用案例
- 状态需要跨路由持久化。
- 多个相距较远的组件依赖同一数据。
- 需要集中缓存或同步。
- 通过 DevTools 调试很重要。
- 该状态真正代表全局关注点(例如身份验证、功能标记、全局 UI 偏好、共享的缓存 API 数据、通知)。
范围约束
- 保持 store 小且专注。
- 避免把仅用于 UI 的状态 放进去。
- 只暴露最小的响应式表面 作为 store 的公共 API。
- 将 store 视作库的合约部分,而不是通用的数据桶。
结论
全局 store 功能强大——但强大需要克制。若有意使用,它能简化你的架构;若随意使用,它会悄然侵蚀架构。保持意图明确,限制作用域,在合适的时候让本地状态保持本地。
祝编码愉快! 🖥️