Pinia 状态管理:比 Vuex 更简单

Pinia 状态管理:比 Vuex 更简单

当项目变大,多个组件需要共享数据时,就需要状态管理。Pinia 是 Vue 3 官方推荐的状态管理库,比 Vuex 更简单。

安装

pnpm add pinia

main.ts 中注册:

import { createApp } from 'vue'
import App from './App.vue'
import { createPinia } from 'pinia'

const app = createApp(App)
app.use(createPinia())
app.mount('#app')

创建第一个 Store

创建 src/stores/counter.ts

import { defineStore } from 'pinia'
import { ref } from 'vue'

export const useCounterStore = defineStore('counter', () => {
  const count = ref(0)

  function increment() {
    count.value++
  }

  function reset() {
    count.value = 0
  }

  return { count, increment, reset }
})

在组件中使用

<script setup lang="ts">
import { useCounterStore } from '../stores/counter'

const counterStore = useCounterStore()
</script>

<template>
  <p>计数:{{ counterStore.count }}</p>
  <button @click="counterStore.increment">+1</button>
  <button @click="counterStore.reset">重置</button>
</template>

Store 的两种写法

组合式(推荐)

refcomputed,更像 Vue 3 Composition API:

export const useCounterStore = defineStore('counter', () => {
  const count = ref(0)
  const double = computed(() => count.value * 2)

  function increment() {
    count.value++
  }

  return { count, double, increment }
})

选项式

stategettersactions

export const useCounterStore = defineStore('counter', {
  state: () => ({
    count: 0
  }),
  getters: {
    double: (state) => state.count * 2
  },
  actions: {
    increment() {
      this.count++
    }
  }
})

推荐组合式,TypeScript 支持更好。

多组件共享状态

任何组件都可以使用 store,修改会同步到所有使用的地方。

<!-- ComponentA.vue -->
<script setup>
const store = useCounterStore()
store.increment()
</script>

<!-- ComponentB.vue -->
<script setup>
const store = useCounterStore()
console.log(store.count) // 已经 +1 了
</script>

getters

计算属性,类似 computed:

export const useUserStore = defineStore('user', () => {
  const firstName = ref('张')
  const lastName = ref('三')

  const fullName = computed(() => lastName.value + firstName.value)

  return { firstName, lastName, fullName }
})

使用:

<script setup>
const userStore = useUserStore()
</script>

<template>
  <p>{{ userStore.fullName }}</p>
</template>

actions

Actions 是修改状态的方法,可以是异步的:

export const useUserStore = defineStore('user', () => {
  const userInfo = ref(null)

  async function fetchUser(id: string) {
    const res = await fetch(`/api/user/${id}`)
    userInfo.value = await res.json()
  }

  function updateName(name: string) {
    if (userInfo.value) {
      userInfo.value.name = name
    }
  }

  return { userInfo, fetchUser, updateName }
})

持久化

浏览器刷新后状态会丢失,需要持久化可以装插件:

pnpm add pinia-plugin-persistedstate

注册:

import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'

const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)

使用:

export const useUserStore = defineStore('user', () => {
  const token = ref('')

  return { token }
}, {
  persist: true // 开启持久化
})

Pinia vs Vuex

特性PiniaVuex
API简洁相对复杂
TypeScript原生支持好需要装饰器
体积稍小稍大
调试工具支持支持
文档清晰较复杂

Vue 3 项目推荐用 Pinia,更简单、更好维护。

总结

  • defineStore 创建 store
  • ref 定义状态,computed 定义 getter,function 定义 action
  • 组合式写法更推荐
  • 组件中通过 useStore() 使用
  • pinia-plugin-persistedstate 可以做持久化

下篇讲组件间通信,包括 props、emit 和 Pinia 的组合使用。

最后更新 4/30/2026, 8:57:45 AM