Pinia 入门
# Pinia 入门
官方文档:Pinia | The intuitive store for Vue.js (opens new window)
# 一、为什么要用 Pinia?它替代了 Vuex
- Vuex:在 Vue2 时代的官方状态管理库;
- Pinia:轻量级状态管理方案,Vue3 官方推荐,API 更简洁、学习成本低、TypeScript 友好。
- 类比后端:就像 Spring 中的 Service/Bean,用来管理全局或跨组件的“共享状态”。
# 二、安装与创建 Store
# 1. 安装 Pinia
npm install pinia
1
# 2. 在项目中注册 Pinia(main.js)
import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';
import router from './router';
const app = createApp(App);
app.use(createPinia());
app.use(router);
app.mount('#app');
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 三、定义第一个 Store
// src/stores/user.js
import { defineStore } from 'pinia';
// storeId:唯一标识
export const useUserStore = defineStore('user', {
// state:存放数据
state: () => ({
id: null,
name: '',
token: ''
}),
// getters:计算属性(类似 Vue 组件中的 computed)
getters: {
isLoggedIn: (state) => !!state.token
},
// actions:方法(可异步,可修改 state;类似 Service)
actions: {
login(payload) {
// 假设调用接口获取 token
this.id = payload.id;
this.name = payload.name;
this.token = payload.token;
// 同时也可以持久化到 localStorage
localStorage.setItem('token', payload.token);
},
logout() {
this.id = null;
this.name = '';
this.token = '';
localStorage.removeItem('token');
}
}
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 四、在组件中使用 Store
<script setup>
import { onMounted } from 'vue';
import { useUserStore } from '@/stores/user';
const userStore = useUserStore();
// 读取 state
console.log(userStore.name, userStore.isLoggedIn);
// 调用 action
function handleLogin() {
userStore.login({ id: 1, name: 'Alice', token: 'abc123' });
}
</script>
<template>
<div>
<p v-if="userStore.isLoggedIn">欢迎,{{ userStore.name }}</p>
<button @click="handleLogin">登录</button>
<button @click="userStore.logout">登出</button>
</div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 五、异步操作与 API 调用
在 actions 中可以写 async/await
,配合前文 Axios 封装:
// src/stores/user.js
import { defineStore } from 'pinia';
import http from '@/utils/request';
export const useUserStore = defineStore('user', {
state: () => ({ id: null, name: '', token: '' }),
getters: { isLoggedIn: (s) => !!s.token },
actions: {
async loginAPI(credentials) {
const res = await http.post('/login', credentials);
this.id = res.id;
this.name = res.name;
this.token = res.token;
localStorage.setItem('token', res.token);
}
}
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
组件中直接调用:
await userStore.loginAPI({ username, password });
1
# 六、持久化与插件
- 持久化:可用
pinia-plugin-persistedstate
将 state 自动同步到localStorage
。 - 安装插件并配置:
npm install pinia-plugin-persistedstate
// main.js
import { createPinia } from 'pinia';
import piniaPersist from 'pinia-plugin-persistedstate';
const pinia = createPinia();
pinia.use(piniaPersist);
app.use(pinia);
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
在 Store 中开启持久化:
export const useUserStore = defineStore('user', {
state: () => ({ token: '' }),
persist: true // 自动持久化整个 state
});
1
2
3
4
2
3
4
# 七、模块化与多人协作最佳实践
- 每个业务域建一个 Store(如
user.js
、cart.js
、settings.js
),清晰职责。 - State 只存必须共享的数据,组件内部状态用
ref
/reactive
即可。 - Getters 只做计算,不改 state,Actions 负责异步和修改。
- 跨 Store 调用:在一个 action 中,可以引用另一个 Store 实例。
import { useCartStore } from './cart';
actions: {
addToCart(product) {
const cart = useCartStore();
cart.add(product);
}
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 八、实战小练习
- 用户登录:登录后将用户信息存在
user
Store 中,控制导航守卫跳转。 - 购物车功能:创建
cart
Store,包含items
、total
,实现添加、删除商品动作。 - 全局设置:创建
settings
Store,存放主题色、语言选择,并在界面中读取、修改。
# 九、总结
概念 | Java 后端类比 | Pinia |
---|---|---|
Bean 管理 | Spring Bean | defineStore / useXxxStore |
服务层 | Service Layer | Store Actions(可异步) |
全局状态 | Static / 单例 | Pinia(跨组件共享) |
持久化 | 缓存 / DB | 插件持久化 localStorage / sessionStorage |
依赖注入 | @Autowired | 在组件中直接 useXxxStore() |
上次更新: 2025/5/20 17:42:11