虽然我们的手动状态管理解决方案在简单的场景中已经足够了,但是在大规模的生产应用中还有很多其他事项需要考虑:
- 更强的团队协作约定
- 与 Vue DevTools 集成,包括时间轴、组件内部审查和时间旅行调试
- 模块热更新 (HMR)
- 服务端渲染支持 Pinia 就是一个实现了上述需求的状态管理库,由 Vue 核心团队维护,对 Vue 2 和 Vue 3 都可用。
这篇文章就简单记录一下 pinia 状态管理的封装过程。 首先新建一个 store 文件夹,再 store 文件夹中新建一个文件夹 module,在这里可以放多个 store,代表不同的模块,模块化管理。每一个 store 都是一个 ts 文件,里面的代码大致如下:
import { defineStore } from 'pinia'
import { ref } from 'vue'
import constant from '../../global/constant'
export const useUserStore = defineStore('user', () => {
const isMasterMode = ref(localStorage.getItem(constant.isMasterMode) ? localStorage.getItem(constant.isMasterMode) : false);
// 账号类型参数,master 代表主管账号,employee 代码员工账号,admin 代表管理员账号
const accountType = ref('employee')
const token = ref(localStorage.getItem(constant.token))
/**
* 将工作模式存储到本地
*/
function saveInfo(state:any){
localStorage.setItem(constant.isMasterMode, state);
isMasterMode.value = state;
}
/**
* 添加 token 到本地
*/
async function addToken(token:any){
localStorage.setItem(constant.token, token);
}
/**
* 删除 token
*/
function removeToken() {
localStorage.removeItem(constant.token);
}
return { isMasterMode, accountType, token, saveInfo, addToken, removeToken }
})
这里采用的是组合式 setup store 的代码写法,ref() 就相当于 state 属性,computed() 就是 getters, function() 就是 ations, 在 pinia 中是没有 mutations 的。 在 store 文件夹中再新建一个 index.ts 文件,文件代码如下:
import { createPinia } from 'pinia';
import { useUserStore } from './module/user'
import { useTrackingStore } from './module/tracking'
import { useCustomerStore } from './module/customer'
import { useCommonStore } from './module/common'
import { useMessageStore } from './module/message'
import { useSetupStore } from './module/setup'
import { useAdminStore } from './module/admin'
import { useDataStore } from './module/data'
const pinia = createPinia();
const useStore = () => {
return {
user: useUserStore(pinia),
tracking: useTrackingStore(pinia),
customer: useCustomerStore(pinia),
message: useMessageStore(pinia),
setup: useSetupStore(pinia),
admin: useAdminStore(pinia),
data: useDataStore(pinia),
common: useCommonStore(pinia)
}
}
export default useStore
在这个文件里创建 pinia 实例,将 module 文件夹中的 store import 进来,这样就完成了 pinia 的封装,然后在 main.ts 文件中进行全局注册:
import { createPinia } from 'pinia';
const pinia = createPinia();
app.use(pinia);
这样我们就可以在其他 vue 文件中使用了,使用方法如下访问 state 和 actions:
<script setup lang="ts">
import useStore from '../store/index';
const { user } = useStore()
const accountType = ref(user.accountType)
user.saveInfo("")
user.removeToken();
<script/>
虽然我们前面定义了一个 store,但在 setup() 调用 useStore() 之前,store 实例是不会被创建的,需要在不同的文件中去定义 store。
还可以通过 store 的 $subscribe() 方法侦听 state 及其变化
<script setup lang="ts" >
import useStore from '../store';
import axios from 'axios';
const { common } = useStore()
common.$subscribe((state:any) => {
showProgress.value = true;
loading.value = true;
curProgress.value = state.curProgress;
})
</script>
也可以通过 action 去修改 state 的值, 直接调用 function, 当然也可以直接赋值。代码如下:
<script setup lang="ts">
import useStore from '../store/index';
const { user } = useStore()
user.saveInfo("123");
user.isMasterMode = true;
<script/>
最后,再总结一下 Pinia 和 VUEX 的区别, 主要有以下几点:
- pinia 它没有 mutation,他只有 state,getters,action【同步、异步】使用他来修改 state 数据
- pinia 语法上比 vuex 更容易理解和使用,灵活
- pinia 没有 modules 配置,每一个独立的仓库都是 definStore 生成出来的
- pinia state 是一个对象返回一个对象和组件的 data 是一样的语法
- 完整的 TypeScript 支持:与在 vuex 中添加 TypeScript 相比,添加 TypeScript 更容易
一般来说 vue2 使用 vuex,vue3 使用 pinia, 以上就是状态管理 Pinia 的基本封装和使用, 如有更多内容再进行补充。