状态管理
本文档介绍如何使用 Pinia 进行状态管理。
Pinia 简介
Pinia 是 Vue 3 官方推荐的状态管理库,具有以下特点:
- 完整的 TypeScript 支持
- 更简洁的 API
- 模块化设计
- 支持 Vue DevTools
创建 Store
基础 Store
typescript
// src/store/modules/user.ts
import { defineStore } from 'pinia';
import { ref } from 'vue';
export const useUserStore = defineStore('user', () => {
const userInfo = ref<UserInfo | null>(null);
const token = ref('');
function setUserInfo(info: UserInfo) {
userInfo.value = info;
}
function setToken(newToken: string) {
token.value = newToken;
}
function logout() {
userInfo.value = null;
token.value = '';
}
return {
userInfo,
token,
setUserInfo,
setToken,
logout
};
});持久化 Store
typescript
import { defineStore } from 'pinia';
import { ref } from 'vue';
export const useUserStore = defineStore('user', () => {
const userInfo = ref<UserInfo | null>(null);
return {
userInfo
};
}, {
persist: {
enabled: true,
strategies: [
{
key: 'user',
storage: localStorage
}
]
}
});使用 Store
在组件中使用
vue
<script setup lang="ts">
import { useUserStore } from '@/store/modules/user';
const userStore = useUserStore();
// 访问状态
console.log(userStore.userInfo);
// 修改状态
userStore.setUserInfo({
id: '1',
username: 'admin'
});
// 调用方法
userStore.logout();
</script>在 Composition API 中使用
typescript
import { useUserStore } from '@/store/modules/user';
export function useAuth() {
const userStore = useUserStore();
async function login(username: string, password: string) {
const result = await loginApi({ username, password });
userStore.setToken(result.token);
userStore.setUserInfo(result.userInfo);
}
return {
login
};
}常用 Store
用户 Store
typescript
// src/store/modules/user.ts
export const useUserStore = defineStore('user', () => {
const userInfo = ref<UserInfo | null>(null);
const token = ref('');
const permissions = ref<string[]>([]);
const roles = ref<string[]>([]);
const isLogin = computed(() => !!token.value);
async function getUserInfo() {
const result = await getUserInfoApi();
userInfo.value = result.userInfo;
permissions.value = result.permissions;
roles.value = result.roles;
}
function hasPermission(permission: string) {
return permissions.value.includes(permission);
}
return {
userInfo,
token,
permissions,
roles,
isLogin,
getUserInfo,
hasPermission
};
});应用 Store
typescript
// src/store/modules/app.ts
export const useAppStore = defineStore('app', () => {
const collapsed = ref(false);
const theme = ref<'light' | 'dark'>('light');
const locale = ref('zh-CN');
function toggleCollapsed() {
collapsed.value = !collapsed.value;
}
function setTheme(newTheme: 'light' | 'dark') {
theme.value = newTheme;
}
return {
collapsed,
theme,
locale,
toggleCollapsed,
setTheme
};
});权限 Store
typescript
// src/store/modules/permission.ts
export const usePermissionStore = defineStore('permission', () => {
const routes = ref<RouteRecordRaw[]>([]);
const menus = ref<MenuType[]>([]);
async function generateRoutes() {
const menuList = await getMenuListApi();
routes.value = transformMenuToRoutes(menuList);
menus.value = transformMenuToMenus(menuList);
}
return {
routes,
menus,
generateRoutes
};
});Store 组合
typescript
export function useAuth() {
const userStore = useUserStore();
const permissionStore = usePermissionStore();
const router = useRouter();
async function login(username: string, password: string) {
// 登录
const result = await loginApi({ username, password });
userStore.setToken(result.token);
// 获取用户信息
await userStore.getUserInfo();
// 生成路由
await permissionStore.generateRoutes();
// 跳转首页
router.push('/dashboard');
}
return {
login
};
}最佳实践
- 模块化:按功能划分 Store
- 类型安全:使用 TypeScript 定义类型
- 持久化:敏感数据使用 sessionStorage
- 命名规范:使用
use前缀 - 避免直接修改:通过方法修改状态