Skip to content

状态管理

本文档介绍如何使用 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
  };
}

最佳实践

  1. 模块化:按功能划分 Store
  2. 类型安全:使用 TypeScript 定义类型
  3. 持久化:敏感数据使用 sessionStorage
  4. 命名规范:使用 use 前缀
  5. 避免直接修改:通过方法修改状态

参考资源

MIT License