vue中使用pinia实现状态管理
大家一定在vue中还见过 useXXXStore这样的函数,用来实现状态管理的。可以把它当成一个永远存在的组件,每个组件都可以读取和写入它。它有三个概念,state、getter 和 action,我们可以假设这些概念相当于组件中的 data
、 computed
和 methods
。
而它通过use开头,正是因为它也符合组合式函数风格的约定。和useXXX函数一样,它写在一个js/ts文件中。
最后在一起分析一下,再vue的vben框架中,是如何使用这个功能的。
pinia插件的优点
- Devtools 支持
- 追踪 actions、mutations 的时间线
- 在组件中展示它们所用到的 Store
- 让调试更容易的 Time travel
- 热更新
- 不必重载页面即可修改 Store
- 开发时可保持当前的 State
- 插件:可通过插件扩展 Pinia 功能
- 为 JS 开发者提供适当的 TypeScript 支持以及自动补全功能。
- 支持服务端渲染
建立这个“永久组件”的例子
引入pinia插件中的 defineStore 来建立,它的第一个参数要求是一个独一无二的名字(类似一个ID),第二个参数可接受两类值:Setup 函数或 Option 对象。
import { defineStore } from 'pinia'export const useCounterStore = defineStore('counter', {state: () => ({ count: 0 })// 类似于组件中computed的getters: { doubleCount: (state) => state.count * 2,},actions: {increment() {this.count++},},
})
在组件中调用
组件中可以在setup中通过 useCounterStore()获得一个Store实例;再通过这个实例能够访问其中左右内容,并且是一直存在的(例子中counter的累加不会被清0)
<script setup>
import { useCounterStore } from '@/stores/counter'
const counter = useCounterStore()
counter.count++ // 修改count
counter.increment() // 调用action
</script>
<template><!-- 模版中也可以直接访问 store 中的 state --><div>Current Count: {{ counter.count }}</div><div>Current doubleCount: {{ counter.doubleCount }}</div>
</template>
vben框架中如何使用了useXXXStore
首先,适用于记录了网站的登录用户相关信息,我们可以通过这个方法访问
src\store\modules\user.ts
export const useUserStore = defineStore({id: 'app-user',state: (): UserState => ({// user infouserInfo: null,// tokentoken: undefined,// roleListroleList: [],// Whether the login expiredsessionTimeout: false,// Last fetch timelastUpdateTime: 0,}),getters: {getUserInfo(state): UserInfo {return state.userInfo || getAuthCache<UserInfo>(USER_INFO_KEY) || {};},getToken(state): string {return state.token || getAuthCache<string>(TOKEN_KEY);},// 省略},actions: {setToken(info: string | undefined) {this.token = info ? info : ''; // for null or undefined valuesetAuthCache(TOKEN_KEY, info);},setRoleList(roleList: RoleEnum[]) {this.roleList = roleList;setAuthCache(ROLES_KEY, roleList);},// 省略},
}
可以看到源码中是没有返回的,也就是不需要接收这个“组合式函数”的结果,而是接收一个对象,通过对象访问。
在vben管理权限的组合式函数(他负责管理权限,其中返回的方法hasPermission实现了按钮级别的权限管理功能)中,就调用了这个状态:
src\hooks\web\usePermission.ts
import { useUserStore } from '/@/store/modules/user';
// User permissions related operations
export function usePermission() {const userStore = useUserStore();const appStore = useAppStore();const permissionStore = usePermissionStore();const { closeAll } = useTabs(router);// 省略
}