Vue3 TypeScript 配置 Vuex4
本文记录
Ts版的Vue3项目配置Vuex。
目录 ./src/store 。
├─ store
│ ├─ index.ts
│ └─ interface.ts
首先看 ./src/store/index.ts ,这里是整个 store 的入口,里面定义并默认导出了 createStore 方法创建的 store 供整个项目使用。
import { InjectionKey } from 'vue';
import { createStore, Store } from 'vuex';
import RootStateTypes from '@/store/interface';
export default createStore<RootStateTypes>({
state: {
test:'test'
},
getters :{
},
mutations: {
CHANGE_TEST(state,val){
state.test = val;
}
},
actions: {
},
modules: {
testModule
}
});
export const key: InjectionKey<Store<RootStateTypes>> = Symbol('vue-store');
InjectionKey方法为创建并使用定义state时提供唯一的key,用到了ES6的Symbol。
./src/store/interface.ts ,定义并导出了所用状态的接口。
export default interface RootStateTypes{
test: string;
}
./src/main.ts 中引入 store
import { createApp } from 'vue'
import store, { key } from './store'
...
createApp(App as any)
.use(store,key)
...
- 注意引入方式,这里引入了之前的唯一值
key,并在createApp的use方法中和store一起传入
测试
<template>
<div>
<p>{{moduleTest}}</p>
<button @click="handlerChnage">测试</button>
</div>
</template>
<script lang="ts">
import { computed } from 'vue';
import { useStore } from 'vuex';
import { key } from '@/store'
export default {
name: 'Test',
setup(){
const store = useStore(key);
let moduleTest = computed(()=>store.state.test);
const handlerChnage = () => {
store.commit('CHANGE_TEST','test2021');
}
return {
moduleTest,
handlerChnage
}
}
};
</script>
- 这里的
import { useStore } from 'vuex';import { key } from '@/store';两条语句分别引入useStore和key - 调用时
const store = useStore(key);也要传入key
每次页面中使用时都要引入并传入 key 有些繁琐,我们可以在 ./src/store/index.ts 中统一导出。
import { InjectionKey } from 'vue';
import { createStore, Store, useStore as baseUseStore } from 'vuex';
import RootStateTypes from '@/store/interface';
export default createStore<RootStateTypes>({
state: {
test:'test'
},
getters :{
},
mutations: {
CHANGE_TEST(state,val){
state.test = val;
}
},
actions: {
},
modules: {
testModule
}
});
export const key: InjectionKey<Store<RootStateTypes>> = Symbol('vue-store');
export function useStore(){
return baseUseStore(key);
}
有两处改变:
useStore as baseUseStore通过 TS 的 as 语法从vuex中引入useStore- 最后导出函数
useStore,相当于包装一下vuex中的useStore方法,传入key。
优化后再测试,代码会有所简化。
import { useStore } from '@/store';
export default {
...
setup(){
const store = useStore();
...
}
...
}
- 不需要引入
key,也不需要把key当作参数传入useStore方法。
配置子模块
需要修改一下目录 ./src/store 。
├─ store
│ ├─ modules
│ │ ├─ test
│ │ │ ├─ index.ts
│ │ │ └─ interface.ts
│ ├─ index.ts
│ └─ interface.ts
-
创建 ./src/store/modules/ 文件夹。
-
为了测试现在此目录创建 test 文件夹。
-
test 相当于一个模块,在这个目录中再创建 index.ts
(state)和 interface(接口)。
./src/store/modules/test/index.ts
import { Module } from 'vuex';
import RootStateTypes from '@/store/interface';
import TestModuleTypes from '@/store/modules/test/interface';
const testModule: Module<TestModuleTypes,RootStateTypes> = {
namespaced: process.env.NODE_ENV !== 'production',
state: {
name: 'testmodule',
count: 0
},
mutations: {
ADD_COUNT(state){
state.count += 1;
}
},
actions: {
},
modules: {
}
}
export default testModule;
- 整体思路和 ./src/store/index.ts 差不多。只是从
vuex中引入了Module作为输出类型。 namespaced命名空间的使用可提高模块的封装性和可复用性。
./src/store/modules/test/interface.ts
export default interface TestModuleTypes{
name: string;
count: number;
}
- 定义子模块的类型。
根模块两个文件的修改:
先看 ./src/store/interface.ts
import TestModuleTypes from '@/store/modules/test/interface'
export default interface RootStateTypes{
test: string;
}
export interface AllStateTypes extends RootStateTypes{
testModule: TestModuleTypes;
}
- 引入了刚定义的子模块类型
TestModuleTypes - 通过接口继承的方式定义
AllStateTypes接口,里面包含全部子模块接口。
再修改 ./src/store/index.ts
import { InjectionKey } from 'vue';
import { createStore, Store, useStore as baseUseStore } from 'vuex';
import RootStateTypes, { AllStateTypes } from '@/store/interface';
// 引入子模块
import testModule from '@/store/modules/test';
export default createStore<RootStateTypes>({
state: {
test:'test'
},
getters :{
},
mutations: {
CHANGE_TEST(state,val){
state.test = val;
}
},
actions: {
},
modules: {
testModule
}
});
export const key: InjectionKey<Store<RootStateTypes>> = Symbol('vue-store');
export function useStore<T=AllStateTypes>(){
return baseUseStore<T>(key);
}
- 引入刚定义的
AllStateTypes子模块接口。 - 导入对应的子模块
testModule,并把它加入到默认导出的createStore的modules中 - 最后导出的
useStore方法添加默认是AllStateTypes的泛型
测试子模块
<template>
<div>
<p>{{testModuleName}}</p>
<p>{{testModuleCount}}</p>
<button @click="handlerCount">添加</button>
</div>
</template>
<script lang="ts">
import { computed } from 'vue';
import { useStore } from '@/store';
export default {
name: 'Test',
setup(){
const store = useStore();
const testModuleName = computed(()=>store.state.testModule.name);
const testModuleCount = computed(()=>store.state.testModule.count);
const handlerCount = () => {
store.commit('testModule/ADD_COUNT');
}
return {
testModuleName,
testModuleCount,
handlerCount
}
}
};
</script>
- 通过
store.state.模块名的方式引用到子模块。 - 注意
store.commit传参的方式'testModule/ADD_COUNT',是'模块名/方法名'
转载自:https://juejin.cn/post/6992763925284519943