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 变化
相关推荐
小高0072 小时前
🤔函数柯里化:化繁为简的艺术与实践
前端·javascript·面试
却尘2 小时前
React useMemo 依赖陷阱:组件重挂载,状态无限复原
前端·javascript·react.js
Asort2 小时前
JavaScript 从零开始(三):浏览器控制台与VS Code协同工作环境搭建详解
前端·javascript
跟橙姐学代码2 小时前
自动化邮件发送的终极秘籍:Python库smtplib与email的完整玩法
前端·python·ipython
我是ed2 小时前
# vue3 实现甘特图
前端
m0_616188492 小时前
el-table的隔行变色不影响row-class-name的背景色
前端·javascript·vue.js
zheshiyangyang2 小时前
Vue3组件数据双向绑定
前端·javascript·vue.js
xw53 小时前
uni-app项目支付宝端Input不受控
前端·uni-app·支付宝
大翻哥哥3 小时前
Python上下文管理器进阶指南:不仅仅是with语句
前端·javascript·python