必须使用@dcloudio/pinia而非官方pinia,因其专为uni-app多端定制,修复ssr时机、storage适配等问题;持久化须用pinia-plugin-unistorage,它自动路由至uni.setstoragesync/getstoragesync,避免小程序报错。

uni-app 项目里用 Pinia,别装 pinia 官方包,得装 @dcloudio/pinia —— 否则 H5 和小程序端行为不一致,运行时可能报 createPinia is not a function 或直接白屏。
为什么 uni-app 不能直接 npm install pinia
uni-app 的 Vue 运行时做了定制,尤其是小程序和 App 端的基座(runtime)与标准 Vue 不完全兼容。官方维护的 @dcloudio/pinia 是针对 uni-app 多端环境打过补丁的版本,修复了 SSR 初始化时机、跨平台 storage 适配、devtools 注入等问题。2026 年 4 月起,HBuilderX 4.14+ 已内置该适配版,但 CLI 项目仍需手动安装。
- 装
pinia(官方版):H5 可能正常,但微信小程序编译会失败,或运行时报Cannot read property 'use' of undefined - 装
@dcloudio/pinia:各端统一,且与pinia-plugin-unistorage兼容性好 - 旧项目升级注意:若之前用 HBuilderX
main.js 中 store 初始化顺序不能错
Pinia 实例必须在 createSSRApp(或 createApp)之后、app.use(store) 之前创建并注入,否则组件内调用 useXXXStore() 会返回 undefined。
- 错误写法:
const store = createPinia()放在createSSRApp外部 —— 此时 Vue 尚未初始化,createPinia拿不到当前实例上下文 - 正确位置:在
createApp函数体内,紧接const app = createSSRApp(App)之后 - 别用条件编译包裹 store 引入,比如
/* #ifdef MP-WEIXIN */ import { createPinia } from '@dcloudio/pinia' /* #endif */—— JS 模块导入不走条件编译,会导致 H5 端找不到模块
export function createApp() {
const app = createSSRApp(App)
// ✅ 正确:这里初始化
const pinia = createPinia()
app.use(pinia)
return { app, pinia }
}
defineStore 里 state 必须用函数返回,别直接写对象
Pinia 要求 state 是一个返回初始状态的函数,否则在多实例场景(如小程序页面跳转再返回)下,state 会被所有实例共享,造成数据污染。
- 错误写法:
state: () => ({ count: 0 })看似对,但如果用了reactive({})包裹外部对象,就破坏了响应式隔离 - 推荐写法:用
ref或reactive在函数体内定义,例如const count = ref(0),然后return { count } - 注意嵌套对象:如果 state 里有深层结构,用
reactive更方便;但若需解构后仍保持响应式,优先用多个ref
import { defineStore, ref } from 'pinia'
export const useUserStore = defineStore('user', () => {
const profile = ref({ name: '', avatar: '' })
const token = ref('')
const isLoggedIn = ref(false)
return { profile, token, isLoggedIn }
})
持久化必须用 pinia-plugin-unistorage,不是 persistedstate
pinia-plugin-persistedstate 默认依赖 localStorage,在小程序、App 等非 H5 环境下会直接报错。uni-app 需要的是能自动路由到 uni.setStorageSync / uni.getStorageSync 的插件,也就是 pinia-plugin-unistorage。
- 安装命令:
yarn add pinia-plugin-unistorage(npm 同理) - 注册方式:在
createPinia()后链式调用.use(unistorage()),不要单独app.use() - 配置粒度:可按 store 名称或 state 字段精确控制哪些数据持久化,例如只存
token和theme,避免把临时 UI 状态也写进 storage
import { createPinia } from '@dcloudio/pinia'
import { unistorage } from 'pinia-plugin-unistorage'
const pinia = createPinia().use(unistorage({
key: 'uni_app_store',
storage: uni // 自动适配各端
}))
最容易被忽略的是:持久化插件不会自动恢复初始 state,你得在 store 的 state 函数里主动从 uni.getStorageSync 读一次,或者确保插件配置了 restoreState 选项(新版 unistorage 默认开启)。否则冷启动时用户看到的仍是空 state,直到第一次变更才写入 storage。










