Pinia 组合式 Store:setup 写法与拆分
Options 风格的
defineStore仍然可用,但 Vue 3 项目里更常见的是 setup store。
这篇想讲清楚几件事:setup store 和写 composable 有什么差别、大项目里怎么按域拆 store、以及复用逻辑时怎么避免「到处 import 乱套」。
setup store 是什么:几乎就是在写 composable
defineStore 传一个 setup 函数时:
- 你在里面照常
ref、computed、watch; - 返回什么,外界就拿到什么(方法、state 一起暴露)。
和纯 useXxx() composable 的差别主要是:
- Pinia 给这个实例 全局单例生命周期(在应用级缓存);
- 有 store id、DevTools、插件机制可挂。
所以:
- 跨路由还要存活的状态 → store;
- 组件树内传一传就行 → composable 往往够用。
拆分策略:按域,而不是按文件类型
实践里比较稳的拆法:
- 用户与鉴权(token、profile、权限缓存);
- 业务域(例如订单、商品目录,随产品边界走);
- 纯 UI 全局(主题、语言)单独一块。
避免:
- 一个
globalStore塞所有字段; - 为了「少建文件」把无关 action 堆在一起。
store 之间需要协作时:
- 在 action 里
useOtherStore()调用即可; - 注意 循环依赖:两个 store 互相顶牛时要抽第三层(服务模块或共享 composable)。
storeToRefs:和模板、解构打交道
组合式 store 返回的多是 ref/computed,在组件里:
- 模板里直接用通常没问题;
- 解构时要用
storeToRefs保住响应式; - 方法可以直接解构,一般仍是稳定引用。
团队规范里写清这一条,能少一半「改了不刷新」的疑惑。
复用:composable + store 的组合拳
常见模式:
- 纯逻辑、无全局单例需求 → 抽成 composable,在 store 的
setup里调用; - 需要全局共享 → composable 只被 store 使用,对外仍暴露 store。
这样测试时也可以:
- 单独测 composable;
- 再测 store 与组件集成。
小结:setup store 的本质是「有身份证的全局 composable」
- 拆分按 业务域,文件结构跟着域走;
- 注意 响应式解构 与 store 间依赖 的边界;
- 复用优先 composable 打底 + store 挂全局。
下一篇讲 插件、持久化 与登录态常见落地。