📌 前言
Pinia 是 Vue 官方推荐的新一代状态管理库,完美替代 Vuex,用法更简洁、轻量化,无复杂配置,可以快速上手!
一、先准备一个演示效果
我们将实现两个小案例,贯穿整个 Pinia 知识点:
- 数字求和计算器
- 土味情话列表(接口获取 + 本地存储持久化)

二、快速搭建 Pinia 环境
csharp
# 安装 Pinia(Vue3 专用)
npm i pinia
main.ts 引入并挂载(必须做)
csharp
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
const app = createApp(App)
app.use(createPinia()) // 挂载 Pinia
app.mount('#app')
三、Pinia 核心概念(3 个秒懂)
每个 Store 对应一个全局数据模块,包含 3 个核心:
state→ 存储数据(相当于组件 data)getters→ 计算属性(相当于组件 computed)actions→ 业务方法(相当于组件 methods)
四、定义 Store(存储 + 读取数据)
1. 数字计算器 Store src/store/count.ts
csharp
// 引入defineStore创建store
import { defineStore } from 'pinia'
// 第一个参数:当前store的唯一标识(不能重复)
// 第二个参数:store配置项
export const useCountStore = defineStore('count', {
// 真正存储数据的地方(必须用函数返回,避免数据污染)
state: () => ({
sum: 6 // 要存储的求和数字
}),
// 计算属性:基于state加工数据
getters: {
doubleSum(state) {
return state.sum * 2
}
},
// 方法:处理业务逻辑、修改state
actions: {
increment() {
// this指向当前store实例
this.sum++
}
}
})
2. 情话列表 Store src/store/talk.ts
csharp
import { defineStore } from 'pinia'
export const useTalkStore = defineStore('loveTalk', {
state: () => ({
// 存储土味情话列表
loveTalk: [
{ id: 1, title: '今天你有点怪,哪里怪,怪好看的!' },
{ id: 2, title: '草莓、蓝莓、蔓越莓,今天你想我了没?' },
{ id: 3, title: '心里给你留了一块地,我的死心塌地' }
]
})
})
五、修改数据的 3 种方式(高频考点)
方式 1:直接修改(最简单)
csharp
// 先引入store
const countStore = useCountStore()
// 直接修改state数据
countStore.sum = 666
方式 2:批量修改($patch)
适合一次性修改多个数据,性能更优
csharp
countStore.$patch({
sum: 888,
school: '清华大学'
})
方式 3:通过 action 修改(推荐)
适合带业务逻辑的修改,可传参、写异步 / 同步逻辑
csharp
// store中定义带参数的action
actions: {
increment(val: number) {
this.sum += val
}
}
// 组件中使用
const n = ref(1)
countStore.increment(n.value)
六、storeToRefs 让模板更简洁
作用 : 将 store 中的state/getters转为ref对象,直接解构在模板中使用,不用写store.xxx
关键注意
- Pinia 的
storeToRefs:只转换数据(state/getters),不转换方法 - Vue 的
toRefs:会转换 store 所有内容,不推荐用
csharp
<template>
<div class="count">
<!-- 直接用解构后的sum,简洁易懂 -->
<h2>当前求和为:{{ sum }}</h2>
</div>
</template>
<script setup lang="ts" name="Count">
import { useCountStore } from '@/store/count'
// 引入pinia提供的storeToRefs
import { storeToRefs } from 'pinia'
// 获取store实例
const countStore = useCountStore()
// 转换后解构数据
const { sum } = storeToRefs(countStore)
</script>
七、getters 计算属性详解
作用 :当state中的数据需要加工后再使用 时,用 getters(缓存计算结果,性能更高)
csharp
export const useCountStore = defineStore('count', {
state: () => ({
sum: 6,
school: 'beijing university'
}),
getters: {
// 写法1:常规函数(可通过state访问数据)
doubleSum(state) {
return state.sum * 2
},
// 写法2:箭头函数(更简洁)
doubleSum2: state => state.sum * 2,
// 复杂计算:转大写
upperSchool(state) {
return state.school.toUpperCase()
}
}
})
组件中使用:
csharp
<h2>放大两倍:{{ countStore.doubleSum }}</h2>
<h2>学校大写:{{ countStore.upperSchool }}</h2>
八、$subscribe 状态监听(持久化必备)
作用 :监听 state 变化 ,只要 store 里的数据改变,就会触发回调函数
常用场景:状态持久化(存本地存储)
csharp
// 获取情话store
const talkStore = useTalkStore()
// 订阅状态变化
talkStore.$subscribe((mutation, state) => {
// mutation:变化的信息
// state:最新的state数据
console.log('状态变化了', mutation, state)
// 本地存储持久化情话列表
localStorage.setItem('talkList', JSON.stringify(state.loveTalk))
})
九、组合式写法(Setup 风格)
和 Vue3 组合式 API 写法一致,更灵活、更简洁,支持异步逻辑
csharp
import { defineStore } from 'pinia'
import { reactive } from 'vue'
import axios from 'axios'
import { nanoid } from 'nanoid'
export const useTalkStore = defineStore('loveTalk', () => {
// 1. 定义state(直接用reactive定义)
const loveTalk = reactive(
localStorage.getItem('talkList')
? JSON.parse(localStorage.getItem('talkList')!)
: []
)
// 2. 定义action(方法)
async function getLoveTalk() {
// 异步请求情话接口
const res = await axios.get('https://api.xygeng.cn/one')
// 组装数据
const obj = { id: nanoid(), title: res.data.data.content }
// 更新state
loveTalk.unshift(obj)
}
// 3. 必须return:暴露给组件使用的数据和方法
return {
loveTalk,
getLoveTalk
}
})
🎯 小结
- Pinia 是 Vue 官方新一代状态管理库,比 Vuex 简单
- 核心:state、getters、actions
- 修改数据:直接改 /
$patch/action - 解构用
storeToRefs - 监听用
$subscribe - 支持组合式 API写法,非常灵活