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、模块化设计与架构差异

  1. 模块化复杂度

    • Vuex‌:采用五模块设计(States、Mutations、Getters、Actions、Modules),需通过mutations同步修改状态,actions处理异步操作,流程相对繁琐。
    • Pinia‌:仅需三模块(States、Getters、Actions),允许直接在actions中同步或异步修改状态,API更简洁直观。
  2. 架构模式

    • Vuex‌:全局单例模式,所有组件共享单一状态树,适合集中式管理复杂状态。
    • Pinia‌:分离式设计,每个组件可拥有独立store实,支持扁平化模块拆分,更灵活。

2、兼容性与技术栈支持

  1. Vue版本适配

    • Vuex‌:主要支持Vue 2,Vue 3需使用Vuex 4.x,兼容性受限。
    • Pinia‌:专为Vue 3设计,深度集成Composition API,不支持Vue 2。
  2. TypeScript支持

    • Vuex‌:需额外配置类型声明,类型推断较弱。
    • Pinia‌:原生支持TypeScript,类型推断更完善,适合类型安全开发。

3、性能与开发体验

  1. 体积与性能

    • Pinia‌:体积约1KB,采用ES6语法优化,性能更优。
    • Vuex‌:体积较大,但稳定性强,适合对性能要求不苛刻的场景。
  2. 开发友好性

    • Pinia‌:语法接近Vue组件,减少样板代码,适合快速开发和初学者。
    • Vuex‌:严格遵循Flux架构,适合需要强规范的大型项目。

4、适用场景总结

工具推荐场景核心优势
Vuex 大型复杂项目、Vue 2迁移项目 严格状态管理、丰富插件生态
Pinia Vue 3项目、快速原型开发 轻量灵活、TypeScript友好

选择建议‌:若项目基于Vue 3且追求开发效率,优先选择Pinia;若需维护Vue 2遗留系统或复杂状态逻辑,Vuex更稳妥。

 

posted @ 2025-04-04 21:56  我用python写Bug  阅读(366)  评论(0)    收藏  举报