monorepo在H5项目中的应用(二、vuex使用)

monorepo中使用VUEX

monorepo项目与其他独立项目不同的是,它是由许多独立的项目组合而成的一个项目,各个项目可以独立运行打包,但是他们之间可能复用了一些相同的数据。所以各个项目的状态管理就存在了这样一个情况各个项目都会用到了一些状态数据,比如token,页面级loading的开启关闭(需要配合拦截器)等,但是各个项目中又会管理自己的状态比如项目demo1内存在一个name字段,项目demo2存在一个count字段,这俩又是互不干扰的。所以vuex的设计模式如下
在这里插入图片描述

目录结构的调整

├── config             // vite相关配置
├── src                
|   ├── common         // 通用方法
|   |   ├── store           // 新增目录 
|   |   |   ├── index.ts // store入口
|   |   |   ├── commonModule.ts // 存放通用数据
|   |   |   ├── interface.ts 
|   ├── packages       // 包文件
|   |   ├── demo1
|   |   |   ├── index.html
|   |   |   ├── main.ts
|   |   |   ├── config.json
|   |   |   ├── App.vue
|   |   |   ├── store   // 新增目录 
|   |   |   |   ├── index.ts  // demo1所独有的store
|   |   ├── demo2
|   |   |   ├── index.html
|   |   |   ├── main.ts
|   |   |   ├── App.vue
|   |   |   ├── store   // 新增目录 
|   |   |   |   ├── index.ts  // demo2所独有的store
├── package.json
├── vite.config.ts

代码实现

通用store代码

// src/common/store/commonModule.ts 
export interface ICommonModule { 
  isShowLoading: boolean
  token: string 
 }
export default {
  namespaced: true,
  state() {
    return {
      isShowLoading: false,
      token: ''
    } as ICommonModule
  },
  mutations: {
    showLoading(state: ICommonModule) {
      state.isShowLoading = true
    },
    hideLoading(state: ICommonModule) {
      state.isShowLoading = false
    }
  },
  actions: {}
}
// src/common/store/interface.ts 
import { ICommonModule } from './commonModule'
export interface IStore {
  commonModule: ICommonModule
}

关键代码

// src/common/store/index.ts 
import { createStore, Store, useStore as baseUseStore } from 'vuex'
import { IStore } from './interface'
import { InjectionKey } from 'vue'
import commonModule from './module/commonModule'

const modulesFiles = import.meta.globEager('../../packages/*/store/index.ts')

let modules = Object.keys(modulesFiles).reduce((modules: { [key: string]: any }, path: string) => {
  const moduleName = path.split('packages/').pop().split('/')[0] + 'Module'
  modules[moduleName] = modulesFiles[path]?.default
  return modules
}, {})

Object.keys(modules).forEach(item => {
  modules[item]['namespaced'] = true
})

export const key: InjectionKey<Store<IStore>> = Symbol()

export default createStore<IStore>({
  modules: {
    commonModule,
    ...modules
  }
})

export function useStore() {
  return baseUseStore(key)
}

// src/packages/demo1/store/index.ts 
interface IMono1Module {
  name: string
}

declare module '@store/interface' {
  interface IStore {
    mono1Module: IMono1Module
  }
}

export default {
  state() {
    return {
      name: '测试'
    }
  },
  mutations: {
    test(state) {
      state.name+= 'A'
    }
  },
  actions: {},
  getters: {}
}

思路就是利用viteimport.meta.globEager来自动引入各个独立项目的store,组装进modules内。但是会引入一个问题,打包demo1时会把demo2内的store也打包进来,这样就不合理了。 我这边是通过vite写了个一个自定义插件,打包demo1时会用../../packages/demo1/store/index.ts 替换 ../../packages/*/store/index.ts这样打包后的modules只会存在一个commonModule和一个demo1Module

各个项目中的store要注意的一点是,可以利用declare直接在通用的IStore 中声明自己的类型。

在项目中使用

import { useStore } from '@store'
const store = useStore()
console.log(store.state.mono1Module.name)  // 测试
store.commit('mono1Module/test')  
console.log(store.state.mono1Module.name)  // 测试A
store.commit('commonModule/showLoading')   // 开启loading

简单的使用是没有问题的,而且代码提示,和ts校验都是可以正常生效
在这里插入图片描述
在这里插入图片描述
这个monorepo项目也是用到了axiosaxios拦截器也是项目必不可少的,下一章讲一下这个项目如何配置拦截器的

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值