前言
最近在将之前的后台框架从js改造为ts,其中涉及了很多vue周边生态的类型引入,这里记录一下vuex实现模块化以及Typescript支持
框架版本vue3.x+vite2.x+vuex4.x
文件结构
在store文件夹中放入modules文件夹和index.ts入口文件,modules用于放置单独的模块
代码实现
入口文件
入口文件除了按照官方的实现方式外,需要将每一个模块的State接口引入,引入后放置在RootState接口下。原理上就是将modules中的模块设置为入口文件中store.state
这个对象的属性。
本质上,Vuex 将store 安装到 Vue 应用中使用了 Vue 的 Provide/Inject 特性,这就是 injection key 是很重要的因素的原因。
//index.ts
import { InjectionKey } from "@vue/runtime-core"
import { createStore, Store, useStore as baseUseStore } from "vuex"
import createPersistedState from "vuex-persistedstate"
import { store as lang, LangState } from "./modules/lang"
import { store as router, RouterState } from "./modules/router"
//定义RootState接口,将所有模块类型放入
export interface RootState {
router: RouterState
lang: LangState
}
export const key: InjectionKey<Store<RootState>> = Symbol()
export const store: Store<RootState> = createStore({
modules: { lang, router },
plugins: [
createPersistedState({
paths: ["lang"],
}),
],
})
export function useStore() {
return baseUseStore(key)
}
示例模块
在模块内使用的时候,需要将RootState接口引入
// modules/lang.ts
import { Module } from "vuex"
import { RootState } from "../index"
export interface LangState {
activeLang: string
}
export const store: Module<LangState, RootState> = {
namespaced: true,
state: (): LangState => ({
activeLang: "",
}),
mutations: {
changeLang(state: LangState, lang: string) {
state.activeLang = lang
},
},
}
全局入口文件中引入
import { createApp } from "vue"
import App from "./App.vue"
import { store, key } from "./store"
const app = createApp(App)
app.use(store, key)
app.mount("#app")
使用方式
在引入useStore时,不是从vuex引入,而是从上面store的入口文件index.ts
导出的useStore
引入,这样就不用都重复引入key
和useStore
import { useStore } from '@/store/index'
const store = useStore()
const activeLang = store.state.lang.activeLang
类型代码提示
引入成功后,在vscode中可以看到整个实例化的store都有了类型的代码提示