技术文档中心
首页
React
Vue
TypeScript
Kotlin
React Native
Electron
Android
首页
React
Vue
TypeScript
Kotlin
React Native
Electron
Android
  • Vue2 基础

    • Vue 学习指南
    • Vue2 快速入门
    • Vue2 模板语法
    • Vue2 组件基础
    • Vue2 计算属性与侦听器
    • Vue2 生命周期
  • Vue2 进阶

    • Vue2 组件通信
    • Vue2 插槽详解
    • Vue2 混入与自定义指令
    • Vue2 过渡与动画
    • Vuex 状态管理
  • Vue2 高级

    • Vue2 性能优化
    • Vue2 服务端渲染(SSR)
    • Vue2 源码解析
  • Vue3 基础

    • Vue3 快速入门
    • Vue3 Composition API
    • Vue3 响应式系统
    • Vue3 组件基础
    • Vue3 生命周期
  • Vue3 进阶

    • Vue3 组合式函数
    • Vue3 组件通信
    • Vue3 Teleport 与 Suspense
    • Pinia 状态管理
    • Vue Router 4
  • Vue3 高级

    • Vue3 TypeScript
    • Vue3 性能优化
    • Vue3 测试
    • Vue3 SSR
    • Vue3 源码解析
  • 实战项目

    • Vue2 实战项目
    • Vue3 实战项目
    • Vue2 迁移 Vue3

Pinia 状态管理

安装

yarn add pinia

配置

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

const pinia = createPinia()
const app = createApp(App)

app.use(pinia)
app.mount('#app')

定义 Store

Option Store

// stores/counter.js
import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', {
  state: () => ({
    count: 0,
    name: 'Counter'
  }),
  getters: {
    doubleCount: (state) => state.count * 2,
    doublePlusOne() {
      return this.doubleCount + 1
    }
  },
  actions: {
    increment() {
      this.count++
    },
    async fetchData() {
      const response = await fetch('/api/data')
      this.count = await response.json()
    }
  }
})

Setup Store

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

export const useCounterStore = defineStore('counter', () => {
  const count = ref(0)
  const name = ref('Counter')
  
  const doubleCount = computed(() => count.value * 2)
  
  function increment() {
    count.value++
  }
  
  return { count, name, doubleCount, increment }
})

使用 Store

基本用法

<script setup>
import { useCounterStore } from '@/stores/counter'

const counter = useCounterStore()

// 访问 state
console.log(counter.count)

// 访问 getters
console.log(counter.doubleCount)

// 调用 actions
counter.increment()
</script>

<template>
  <div>{{ counter.count }}</div>
  <button @click="counter.increment">+1</button>
</template>

解构

<script setup>
import { storeToRefs } from 'pinia'
import { useCounterStore } from '@/stores/counter'

const counter = useCounterStore()

// 使用 storeToRefs 保持响应性
const { count, doubleCount } = storeToRefs(counter)

// actions 可以直接解构
const { increment } = counter
</script>

State

访问 state

const counter = useCounterStore()
console.log(counter.count)

修改 state

// 直接修改
counter.count++

// $patch 对象
counter.$patch({
  count: counter.count + 1,
  name: 'New Name'
})

// $patch 函数
counter.$patch((state) => {
  state.count++
  state.items.push({ name: 'shoes' })
})

// $state 替换整个 state
counter.$state = { count: 0, name: 'Counter' }

重置 state

counter.$reset()

Getters

export const useStore = defineStore('main', {
  state: () => ({
    count: 0
  }),
  getters: {
    // 自动推断返回类型
    doubleCount(state) {
      return state.count * 2
    },
    // 访问其他 getters
    doublePlusOne() {
      return this.doubleCount + 1
    },
    // 传递参数
    getUserById: (state) => {
      return (userId) => state.users.find((user) => user.id === userId)
    }
  }
})

Actions

export const useStore = defineStore('main', {
  state: () => ({
    count: 0
  }),
  actions: {
    increment() {
      this.count++
    },
    async fetchData() {
      try {
        const response = await fetch('/api/data')
        this.count = await response.json()
      } catch (error) {
        console.error(error)
      }
    }
  }
})

订阅

订阅 state

const counter = useCounterStore()

counter.$subscribe((mutation, state) => {
  console.log(mutation.type) // 'direct' | 'patch object' | 'patch function'
  console.log(mutation.storeId) // 'counter'
  console.log(state)
})

订阅 actions

counter.$onAction(({
  name,
  store,
  args,
  after,
  onError
}) => {
  console.log(`Action ${name} called`)
  
  after((result) => {
    console.log('Action finished')
  })
  
  onError((error) => {
    console.error('Action failed')
  })
})

插件

// plugins/myPlugin.js
export function myPiniaPlugin(context) {
  context.pinia // 使用 createPinia() 创建的 pinia
  context.app // 使用 createApp() 创建的 app
  context.store // 插件正在扩展的 store
  context.options // 定义 store 的选项对象
  
  // 为每个 store 添加属性
  return {
    secret: 'the cake is a lie'
  }
}

// main.js
const pinia = createPinia()
pinia.use(myPiniaPlugin)
最近更新: 2026/1/27 15:51
Contributors: hailong
Prev
Vue3 Teleport 与 Suspense
Next
Vue Router 4