2、pinia——全局状态管理

Vuex 是 Vue2 时代的强制规范,设计偏笨重、冗余;

Pinia 是 Vue3 专为组合式 API、TS、轻量化设计,功能全覆盖、写法更简单、无冗余完全平替 Vuex,还更好用

vuex缺点
  1. 强制划分 state / getters / mutations / actions 太繁琐

    只能在 mutations 改 state

    异步逻辑必须放 actions

    改个简单数据,要走:组件 dispatch → actions → commit → mutations 改 state

    修改一个state要通过太多嵌套的代码层级

  2. 必须用 this.$store 或 映射函数

    Vue2 选项式还能凑合,到了 Vue3 <script setup>

    • 没有 this

    • 要用 useStore 还得引入辅助函数

    • mapState、mapGetters、mapActions 写法啰嗦、解构麻烦

  3. 模块嵌套 modules 层级太深

    大型项目拆模块后:

    store.modules.user.info.name

    层级嵌套深,取值麻烦,命名容易冲突。

  4. TypeScript 支持差

    Vuex 类型推导很弱,需要额外写大量类型声明,TS 体验极差

pinia的解决方案
1、Pinia 只有三个核心:

state / getters / actions——直接去除了mutations来简化结构

  • 同步、异步修改 state 全都直接写在 actions 里

  • 不需要 commit、不需要 mutations

  • 想改数据:直接改 或 调用 action 就行

Vuex 繁琐流程

组件 → dispatch (action) → commit (mutation) → 修改 state

Pinia 极简流程

组件 → 直接改 state 或 调用 action → 修改 state

2、天然适配 Vue3 <script setup>,没有 this 也能用
<script setup>
import { useUserStore } from '@/stores/user'
const userStore = useUserStore()
// 直接用数据、直接调方法
userStore.name
userStore.login()
</script>
3、扁平化模块,不再嵌套

Pinia 每个仓库都是独立扁平的:

  • 不用嵌套 modules

  • 每个 defineStore 独立命名、互不干扰

  • 引用哪个就导入哪个,结构清晰

4、原生顶级 TS 支持

自动类型推导

state、getters、actions 全部自带类型提示

不用额外定义复杂接口,大型项目类型极其友好

pinia实例

1、main.js全局注册

import { createApp } from 'vue'
import App from './App.vue'
import { createPinia } from 'pinia'
​
// 创建pinia实例
const pinia = createPinia()
​
createApp(App).use(pinia).mount('#app')

2、新建仓库

import { defineStore } from 'pinia'
​
// 定义仓库:唯一id 为 counter
export const useCounterStore = defineStore('counter', {
  // 1. 全局状态(相当于data)
  state: () => ({
    count: 0,
    username: '张三'
  }),
​
  // 2. 计算属性(相当于computed)
  getters: {
    doubleCount: (state) => state.count * 2
  },
​
  // 3. 全局方法:同步 + 异步(相当于methods)
  actions: {
    // 同步修改
    increment() {
      // 这里可以用this,指向当前store
      this.count++
    },
    setName(name) {
      this.username = name
    },
​
    // 异步方法(模拟接口请求)
    async asyncChangeCount() {
      // 模拟接口延迟
      await new Promise(resolve => setTimeout(resolve, 1000))
      this.count += 10
    }
  }
})

3、组件中使用

<template>
  <div>
    <h3>原始值:{{ counterStore.count }}</h3>
    <h3>计算属性双倍值:{{ counterStore.doubleCount }}</h3>
    <h3>用户名:{{ counterStore.username }}</h3>
​
    <!-- 1. 直接改数据 -->
    <button @click="counterStore.count++">直接+1</button>
    
    <!-- 2. 调用pinia同步方法 -->
    <button @click="counterStore.increment">调用action+1</button>
    <button @click="counterStore.setName('李四')">修改名字</button>
​
    <!-- 3. 调用异步方法 -->
    <button @click="counterStore.asyncChangeCount">异步+10</button>
  </div>
</template>
​
<script setup>
// 引入仓库
import { useCounterStore } from '@/stores/counter'
​
// 获取仓库实例,直接就能用
const counterStore = useCounterStore()
</script>

更多推荐