Pinia 深度依赖 Vue 的 Provide/Inject 机制实现 store 跨组件分发,通过 app.use(pinia) 在根节点 provide pinia 实例,useStore() 封装 inject 查找对应 store;非组件环境需手动 inject(piniaSymbol) 获取实例,切勿提前调用或覆盖 piniaSymbol。

Pinia 本身不是靠 Composition API 实现的“模式”,而是深度依赖 Vue 的 Provide/Inject 机制来完成 store 的跨组件分发与自动注入。它把 provide/inject 当作底层通信骨架,再在上面封装出 useStore() 这样的组合式函数。理解这一点,才能真正用好 Pinia 的 composition 风格。
Pinia 如何用 provide 注入实例
应用启动时,你调用 app.use(pinia),这一步本质是:
- Pinia 创建一个全局唯一的 pinia 实例
- 通过 provide(piniaSymbol, pinia) 把它注入到整个组件树根节点
- piniaSymbol 是一个 Symbol 键(如 Symbol('pinia')),确保不会和用户自定义的 provide 冲突
useStore() 其实就是 inject 的封装
你在任意组件中写 const store = useUserStore(),内部执行的是:
- 检查当前是否有活跃的组件上下文(hasInjectionContext)
- 调用 inject(piniaSymbol) 拿到最外层 provide 的 pinia 实例
- 再根据 store id(如 'user')从 pinia 实例里查找或创建对应 store
手动 inject pinia 实例的场景
某些非组件环境(比如工具函数、插件逻辑、测试 setup)无法直接调用 useStore(),这时可主动 inject:
- 在 setup 函数内:const pinia = inject(piniaSymbol)
- 需先 import { piniaSymbol } from 'pinia'
- 拿到 pinia 后,可用 pinia.useStore('user') 手动获取 store
避免常见陷阱
两个高频错误要特别注意:
- 不能在 createApp 之前调用 useStore()——因为此时 pinia 还没被 provide,inject 会返回 undefined
- 不要在 provide 中覆盖 piniaSymbol——否则会切断 Pinia 的自动注入链,导致所有 useStore() 失效

















