Pinia 通过单一数据源、响应式绑定和明确作用域实现安全共享状态;每个 store 聚焦一个业务领域,命名唯一,用箭头函数返回状态对象,组件统一调用 useXXXStore() 获取同一实例,敏感操作封装在 actions 中,避免解构丢失响应性,复杂场景用 provide/inject 或动态 ID 创建隔离实例。

Pinia 在多个组件之间安全共享全局状态,关键在于“单一数据源 + 响应式绑定 + 明确作用域”。它不是靠手动同步或事件广播,而是通过 Vue 的响应式系统自动触发更新,只要所有组件读写的是同一个 store 实例,状态就天然一致。
用 defineStore 创建模块化仓库
每个 store 应聚焦一个业务领域,比如用户、收藏、购物车。避免把所有状态塞进一个大 store,否则容易冲突和难以维护。
- 为每个状态域单独建文件,如 src/stores/useUserStore.js 和 src/stores/useFavoriteStore.js
- store 名称(第一个参数)必须唯一,Pinia 靠它识别实例,重复会导致覆盖
- state 用箭头函数返回对象,确保每次新建 store 实例时状态独立(尤其在 SSR 或多实例场景下)
在组件中统一访问同一实例
所有组件都调用同一个 useXXXStore() 函数,Pinia 内部会返回同一个响应式 store 实例,无需手动创建或传参。
- 直接导入并调用: const userStore = useUserStore()
- 模板中可直接使用 {{ userStore.name }},脚本中可修改 userStore.token = 'xxx'
- 不推荐在 setup 中多次调用同一 store 函数——虽然 Pinia 会复用实例,但语义上应只调用一次并复用返回值
避免状态污染的实操要点
共享不等于随意修改。安全的核心是控制谁改、怎么改、改什么。
- 敏感操作(如登录态变更、权限切换)尽量封装在 actions 中,不在模板里直接赋值 userStore.isLogin = true
- 不要在 store 中直接解构 state 属性(如 const { count } = store),这会丢失响应性;始终通过 store.count 访问
- 若需跨页面保持状态(如搜索条件),配合 pinia-plugin-persistedstate 插件持久化,避免刷新丢失
复杂场景下做状态隔离
当同一页面需要多个同类状态(如同时编辑两份问卷),全局 store 容易互相干扰。这时不应强行塞进一个 store,而应:
- 用 provide/inject 把局部 store 实例注入子树,让每个编辑区拥有自己的 store 实例
- 或动态创建 store: defineStore(`cart-${id}`, {...}),用不同 id 区分作用域
- 避免在 action 内部靠 if-else 判断 activeId 来分支更新——这会让 store 变成“状态路由表”,违背单一职责










