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 info
userInfo: null,
// token
token: undefined,
// roleList
roleList: [],
// Whether the login expired
sessionTimeout: false,
// Last fetch time
lastUpdateTime: 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 value
setAuthCache(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);
// 省略
}