Vue3 状态管理 Pinia 从入门到实战

发布于2026-08-28 14:35 阅读12次 系统讲解 Vue3 官方推荐的状态管理库 Pinia,涵盖 Store 定义、state/getters/actions、组合式与选项式两种写法、持久化插件、模块化组织以及在组件中的使用,附代码示例和实战建议。
# Vue3 状态管理 Pinia 从入门到实战
## 前言
Pinia 是 Vue 官方推荐的状态管理库,替代了 Vuex,API 更简洁、类型推断更好、也支持组合式写法。本文从入门到实战,梳理 Pinia 的核心用法。
## 安装与初始化
```bash
npm install pinia
```
```javascript
// main.js
import { createApp } from "vue";
import { createPinia } from "pinia";
import App from "./App.vue";
const app = createApp(App);
app.use(createPinia());
app.mount("#app");
```
## 定义 Store(选项式)
```javascript
// stores/counter.js
import { defineStore } from "pinia";
export const useCounterStore = defineStore("counter", {
state: () => ({
count: 0,
name: "counter",
}),
getters: {
doubleCount: (state) => state.count * 2,
},
actions: {
increment() {
this.count++;
},
async fetchData() {
const res = await api.getData();
this.count = res.data;
},
},
});
```
## 定义 Store(组合式)
```javascript
// stores/user.js
import { ref, computed } from "vue";
import { defineStore } from "pinia";
export const useUserStore = defineStore("user", () => {
const userInfo = ref(null);
const isLoggedIn = computed(() => !!userInfo.value);
async function login(username, password) {
const res = await api.login({ username, password });
userInfo.value = res.data;
}
function logout() {
userInfo.value = null;
}
return { userInfo, isLoggedIn, login, logout };
});
```
组合式写法和 Composition API 风格一致,更适合熟悉 setup 的开发者。
## 在组件中使用
```javascript
import { useCounterStore } from "./stores/counter";
import { storeToRefs } from "pinia";
const store = useCounterStore();
// 直接访问 state 和 getter
store.count;
store.doubleCount;
store.increment();
// 解构保持响应式:用 storeToRefs
const { count, doubleCount } = storeToRefs(store);
// actions 可以直接解构(actions 是函数)
const { increment } = store;
```
注意:state 和 getters 解构要用 `storeToRefs`,否则丢失响应式。
## 状态持久化
```bash
npm install pinia-plugin-persistedstate
```
```javascript
// main.js
import piniaPluginPersistedstate from "pinia-plugin-persistedstate";
const pinia = createPinia();
pinia.use(piniaPluginPersistedstate);
// stores/user.js
export const useUserStore = defineStore("user", {
state: () => ({ token: "" }),
persist: true, // 默认存 localStorage
});
```
刷新页面状态不丢失,登录态、用户偏好等场景很有用。
## 模块化组织
```
stores/
├── user.js # 用户信息、登录态
├── cart.js # 购物车
├── theme.js # 主题、偏好设置
└── index.js # 可选:统一导出
```
按业务域拆分 Store,避免单个 Store 过大。
## 跨 Store 调用
```javascript
// stores/order.js
import { useUserStore } from "./user";
export const useOrderStore = defineStore("order", {
actions: {
async createOrder() {
const userStore = useUserStore();
const userId = userStore.userInfo.id;
// 使用 userId 创建订单
},
},
});
```
在 action 内部直接调用其他 Store 即可。
## 与 Vuex 的区别
| 特性 | Vuex | Pinia |
|------|------|-------|
| 语法 | 繁琐 | 简洁 |
| mutations | 有 | 移除(合并到 actions) |
| 组合式写法 | 不支持 | 支持 |
| TypeScript | 支持一般 | 原生支持好 |
| 体积 | 较大 | 更小 |
## 实战建议
- 全局共享状态才进 Store,局部状态用组件内部 ref
- 异步请求放 actions,不要在组件里直接改 state
- 用 storeToRefs 保持解构响应式
- 登录态、主题等需要持久化的用 persist 插件
## 小结
Pinia 核心三要素:state(数据)、getters(派生)、actions(操作)。掌握 defineStore 两种写法、storeToRefs 解构、persist 持久化,就能覆盖绝大多数状态管理场景。Vue3 项目首选 Pinia,无需再纠结 Vuex。