Pinia状态管理有哪些常用API?

Pinia 是 Vue.js 的官方状态管理库,它取代了 Vuex,提供了更简洁、直观且类型友好的 API。以下是 Pinia 中最常用的核心 API 及其用法:


1. defineStore() - 定义 Store

这是创建一个 store 的核心 API。它接受一个唯一的 ID 和一个配置对象(或 setup 函数)。

javascript 复制代码
javascript
深色版本
// stores/counter.js
import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', {
  // 状态 (State)
  state: () => ({
    count: 0,
    name: 'Eduardo'
  }),

  // 计算属性 (Getters)
  getters: {
    doubleCount: (state) => state.count * 2,
    // 带参数的 getter
    getByName: (state) => {
      return (name) => state.name === name
    }
  },

  // 动作 (Actions)
  actions: {
    increment() {
      this.count++
    },
    decrement() {
      this.count--
    },
    // 异步操作
    async fetchUser() {
      const res = await fetch('/api/user')
      this.name = await res.json()
    }
  }
})

说明defineStore 返回一个函数(如 useCounterStore),调用它即可获取 store 实例。


2. state - 状态

用于定义 store 中的响应式数据。

  • 必须是一个函数,返回一个包含状态的对象。
  • 可以在组件中直接读取和修改。
yaml 复制代码
javascript
深色版本
state: () => ({
  count: 0,
  todos: []
})

3. getters - 计算属性

类似于 Vue 组件中的 computed,用于派生状态。

  • 接收 state 作为第一个参数。
  • 支持缓存,只有依赖的 state 变化时才会重新计算。
  • 可以接受参数(返回一个函数)。
javascript 复制代码
javascript
深色版本
getters: {
  // 基础 getter
  doubleCount: (state) => state.count * 2,

  // 带参数的 getter
  getTodoById: (state) => {
    return (id) => state.todos.find(todo => todo.id === id)
  }
}

4. actions - 动作

用于定义修改 state 的方法,支持同步和异步操作。

  • 可以通过 this 访问 stategetters 和其他 actions
  • 是修改 state 的唯一推荐方式(虽然可以直接修改,但不推荐)。
javascript 复制代码
javascript
深色版本
actions: {
  increment() {
    this.count++
  },
  async fetchData() {
    const data = await api.getData()
    this.todos = data
  }
}

5. 在组件中使用 Store

在组件中通过调用 useXxxStore() 函数来使用 store。

xml 复制代码
vue
深色版本
<script setup>
import { useCounterStore } from '@/stores/counter'

const counter = useCounterStore()

// 直接访问 state, getters, actions
console.log(counter.count)         // state
console.log(counter.doubleCount)   // getter
counter.increment()                // action
</script>

<template>
  <div>
    <p>Count: {{ counter.count }}</p>
    <p>Double: {{ counter.doubleCount }}</p>
    <button @click="counter.increment">+</button>
  </div>
</template>

注意 :从 store 中解构变量会失去响应性 。如果需要解构,应使用 storeToRefs()


6. storeToRefs() - 保持解构后的响应性

当你想从 store 中解构 state 或 getters 并保持响应性时,使用此工具函数。

xml 复制代码
vue
深色版本
<script setup>
import { storeToRefs } from 'pinia'
import { useCounterStore } from '@/stores/counter'

const counter = useCounterStore()
// ❌ 错误:count 失去响应性
// const { count, doubleCount } = counter

// ✅ 正确:使用 storeToRefs
const { count, doubleCount } = storeToRefs(counter)
const { increment } = counter // actions 不需要,因为不是响应式引用
</script>

7. mapState, mapGetters, mapActions - 映射辅助函数

在选项式 API(Options API)中,可以使用这些辅助函数将 store 的内容映射到组件中。

javascript 复制代码
javascript
深色版本
import { mapState, mapActions } from 'pinia'
import { useCounterStore } from '@/stores/counter'

export default {
  computed: {
    // 映射 state
    ...mapState(useCounterStore, ['count', 'name']),
    // 或者重命名
    ...mapState(useCounterStore, {
      myCount: 'count'
    })
  },
  methods: {
    // 映射 actions
    ...mapActions(useCounterStore, ['increment', 'fetchUser'])
  }
}

8. $reset() - 重置状态

每个 store 实例都暴露一个 $reset() 方法,用于将 state 重置为初始值。

scss 复制代码
javascript
深色版本
const counter = useCounterStore()
counter.$reset() // 将 count 重置为 0

9. $subscribe() - 订阅状态变化

监听 store 的 state 变化,类似于 Vuex 的 subscribe。

javascript 复制代码
javascript
深色版本
const counter = useCounterStore()

// 订阅 state 变化
const unsubscribe = counter.$subscribe((mutation, state) => {
  // mutation: 包含 type 等信息
  // state: 最新的 state
  console.log('State changed:', state.count)
})

// 取消订阅
// unsubscribe()

总结

API 用途
defineStore() 定义一个 store
state 定义响应式数据
getters 定义计算属性
actions 定义修改 state 的方法(支持异步)
useXxxStore() 在组件中使用 store
storeToRefs() 解构 store 时保持响应性
mapState / mapGetters / mapActions 选项式 API 中的映射辅助函数
$reset() 重置 state 到初始值
$subscribe() 监听 state 变化
相关推荐
king王一帅2 小时前
Incremark Solid 版本上线:Vue/React/Svelte/Solid 四大框架,统一体验
前端·javascript·人工智能
智航GIS6 小时前
10.4 Selenium:Web 自动化测试框架
前端·python·selenium·测试工具
前端工作日常7 小时前
我学习到的A2UI概念
前端
徐同保7 小时前
为什么修改 .gitignore 后还能提交
前端
一只小bit7 小时前
Qt 常用控件详解:按钮类 / 显示类 / 输入类属性、信号与实战示例
前端·c++·qt·gui
Mr -老鬼7 小时前
前端静态路由与动态路由:全维度总结与实践指南
前端
颜酱8 小时前
前端必备动态规划的10道经典题目
前端·后端·算法
wen__xvn8 小时前
代码随想录算法训练营DAY10第五章 栈与队列part01
java·前端·算法
大怪v9 小时前
前端佬们!!AI大势已来,未来的上限取决你的独特气质!恭请批阅!!
前端·程序员·ai编程
Mr -老鬼10 小时前
功能需求对前后端技术选型的横向建议
开发语言·前端·后端·前端框架