vue3.0 + TS + AntD 项目开发学习笔记:Pinia 状态管理类封装

126 阅读2分钟

虽然我们的手动状态管理解决方案在简单的场景中已经足够了,但是在大规模的生产应用中还有很多其他事项需要考虑:

  • 更强的团队协作约定
  • 与 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 的基本封装和使用, 如有更多内容再进行补充。