uni-app状态管理之Pinia
一、介绍
uni-app 内置了 Pinia ,Vue 2 项目暂不支持。
Pinia是 Vue 的存储库,它允许您跨组件、页面共享状态。在服务器端以及小型单页应用程序中,您也可以从使用 Pinia 中获得很多好处:
- Devtools 支持
- 追踪 actions、mutations 的时间线
- 在组件中展示它们所用到的 Store
- 让调试更容易的 Time travel
- 热模块更换
- 不必重载页面即可修改 Store
- 开发时可保持当前的 State
- 为 JS 开发者提供适当的 TypeScript 支持以及 自动补全 功能。
目录结构
├── pages
├── static
└── stores
└── mainStore.js
├── App.vue
├── main.js
├── manifest.json
├── pages.json
└── uni.scss
二、使用
1、定义pinia管理的仓库
// store/mainStore.js import { defineStore } from 'pinia'; export const useMainStore = defineStore('main', { state: () => ({ userCount: 0 // 用户数量 }), getters: { doubledCount: state => state.userCount * 2, }, actions: { increment() { this.userCount++; } }, });
2、在main.js声明
import App from './App' import { createSSRApp } from 'vue' import store from '@/store/index.js'; import * as Pinia from 'pinia'; export function createApp() { const app = createSSRApp(App); app.use(store); // vuex与Pinia不冲突,可以一起使用 app.use(Pinia.createPinia()); return { app, Pinia, // 此处必须将 Pinia 返回 } }
3、在组件中使用,三种方式修改state的值
<template>
<view class="content">
<!-- 直接从 store 中访问 state -->
<text>当前用户数量有: {{ mainStore.userCount }}</text>
<text>双倍用户数量有: {{ mainStore.doubledCount }}</text>
<text><button @click="addUser1">直接修改用户数</button></text>
<text><button @click="addUser2">$patch修改用户数</button></text>
<text><button @click="addUser3">action修改用户数</button></text>
</view>
</template>
<script setup lang="ts">
import { computed, onMounted, ref } from 'vue';
import { useMainStore } from '@/store/mainStore.js'
const mainStore= useMainStore();
function addUser1() {
// 1、直接修改state的值
mainStore.userCount++
}
function addUser2() {
// 2、$patch修改state的值
mainStore.$patch({ userCount: mainStore.userCount + 1 })
}
function addUser3() {
// 3、action修改state的值
mainStore.increment()
}
</script>
<style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
</style>
4、如果你还不熟悉 setup() 函数和组合式 API,Pinia 也提供了一组类似 Vuex 的 映射 state 的辅助函数。
你可以用和之前一样的方式来定义 Store,然后通过 mapStores()、mapState() 或 mapActions() 访问:
// store/counterStore.js const useCounterStore = defineStore('counter', { state: () => ({ count: 0 }), getters: { double: (state) => state.count * 2, }, actions: { increment() { this.count++ }, }, }) // store/userStore.js const useUserStore = defineStore('user', { // ... }) // 组件中使用 import { mapState, mapStores, mapActions } from 'pinia' import { useCounterStore } from '@/store/counterStore.js' import { useUserStore } from '@/store/userStore.js' export default defineComponent({ computed: { // 允许访问 this.counterStore 和 this.userStore ...mapStores(useCounterStore, useUserStore) // 允许读取 this.count 和 this.double ...mapState(useCounterStore, ['count', 'double']), }, methods: { // 允许读取 this.increment() ...mapActions(useUserStore, ['increment']), }, })
三、vuex与Pinia区别
1、模块化设计与架构差异
-
模块化复杂度
- Vuex:采用五模块设计(States、Mutations、Getters、Actions、Modules),需通过
mutations同步修改状态,actions处理异步操作,流程相对繁琐。 - Pinia:仅需三模块(States、Getters、Actions),允许直接在
actions中同步或异步修改状态,API更简洁直观。
- Vuex:采用五模块设计(States、Mutations、Getters、Actions、Modules),需通过
-
架构模式
- Vuex:全局单例模式,所有组件共享单一状态树,适合集中式管理复杂状态。
- Pinia:分离式设计,每个组件可拥有独立store实例,支持扁平化模块拆分,更灵活。
2、兼容性与技术栈支持
-
Vue版本适配
- Vuex:主要支持Vue 2,Vue 3需使用Vuex 4.x,兼容性受限。
- Pinia:专为Vue 3设计,深度集成Composition API,不支持Vue 2。
-
TypeScript支持
- Vuex:需额外配置类型声明,类型推断较弱。
- Pinia:原生支持TypeScript,类型推断更完善,适合类型安全开发。
3、性能与开发体验
-
体积与性能
- Pinia:体积约1KB,采用ES6语法优化,性能更优。
- Vuex:体积较大,但稳定性强,适合对性能要求不苛刻的场景。
-
开发友好性
- Pinia:语法接近Vue组件,减少样板代码,适合快速开发和初学者。
- Vuex:严格遵循Flux架构,适合需要强规范的大型项目。
4、适用场景总结
| 工具 | 推荐场景 | 核心优势 |
|---|---|---|
| Vuex | 大型复杂项目、Vue 2迁移项目 | 严格状态管理、丰富插件生态 |
| Pinia | Vue 3项目、快速原型开发 | 轻量灵活、TypeScript友好 |
选择建议:若项目基于Vue 3且追求开发效率,优先选择Pinia;若需维护Vue 2遗留系统或复杂状态逻辑,Vuex更稳妥。

浙公网安备 33010602011771号