如何在 Vuex 4 和 TypeScript 中使用其他存储模块 getter/actions/mutations
Posted
技术标签:
【中文标题】如何在 Vuex 4 和 TypeScript 中使用其他存储模块 getter/actions/mutations【英文标题】:How to use other store module getters/actions/mutations with Vuex 4 and TypeScript 【发布时间】:2021-08-08 19:58:53 【问题描述】:我正在使用 TypeScript 和 Vuex4 开发一个 Vue 3 项目。 现在,我正在使用带有 TS 的 vuex 中的每个商店模块使用样板声明方法。 看起来像这样: 或者如果我的代码可读性不够,这里是我用来指导我的:https://betterprogramming.pub/the-state-of-typed-vuex-the-cleanest-approach-2358ee05d230
//#region Store
export const state: State =
stateVar: null,
isError: false,
;
export const getters: GetterTree<State, RootState> & Getters =
getStateVar: state => state.stateVar,
getIsError: state => state.isError,
;
export const mutations: MutationTree<State> & Mutations =
[ModuleMutationTypes.setStateVar](state: State, payload: StateVarType)
state.stateVar = payload;
,
[ModuleMutationTypes.setIsError](state: State, payload: boolean)
state.isError = payload;
,
;
export const actions: ActionTree<State, RootState> & Actions =
async [ModuleActionTypes.doRequest]( commit, getters )
//do something and commit it
// for example here i would like to access the getters or action from another store how is that possible
commit(ModuleMutationTypes.setStateVar, someValue);
,
;
//#endregion Store
//#region Store Type
export type State =
someStateVar: SomeStateVarType;
isError: boolean;
;
export type Getters =
getStateVar(state: State): someStateVarType;
getIsError(state: State): boolean;
;
export type Mutations<S = State> =
[ModuleMutationTypes.setStateVar](state: S, payload: SomeSTateVarType): void;
[ModuleMutationTypes.setIsError](state: S, payload: boolean): void;
;
export interface Actions
[ModuleActionTypes.doRequest](context: AugmentedActionContext): Promise<any>;
type AugmentedActionContext =
commit<K extends keyof Mutations>(key: K, payload: Parameters<Mutations[K]>[1]): ReturnType<Mutations[K]>;
getters:
[K in keyof Getters]: ReturnType<Getters[K]>;
;
dispatch<K extends keyof Actions>(
key: K,
payload?: Parameters<Actions[K]>[1],
options?: DispatchOptions
): ReturnType<Actions[K]>;
& Omit<ActionContext<State, RootState>, 'commit' | 'getters' | 'dispatch'>;
//#endregion Store Type
//#region Store Module
export type ModuleStore<S = State> = Omit<VuexStore<S>, 'getters' | 'commit' | 'dispatch'> &
commit<K extends keyof Mutations, P extends Parameters<Mutations[K]>[1]>(
key: K,
payload: P,
options?: CommitOptions
): ReturnType<Mutations[K]>;
&
dispatch<K extends keyof Actions>(
key: K,
payload?: Parameters<Actions[K]>[1],
options?: DispatchOptions
): ReturnType<Actions[K]>;
&
getters:
[K in keyof Getters]: ReturnType<Getters[K]>;
;
;
export const store: Module<State, RootState> =
state,
mutations,
getters,
actions,
//namespaced also breaks everything
// But without it, a bigger store might have ***es in namings
// namespaced: true,
;
//#endregion Store Type & Module
现在正如你所见,这让我重复了很多很多东西,但是在 Vuex 5 之前我不知道是否还有其他更好的解决方案。 另外我对 TypeScript 很陌生,我只是使用这个样板作为模板来让我的商店打字。
我的主要问题是:
- 如何访问其他模块的 getter 或特定模块中的操作或突变,如果我可以让 RootGetters 和 RootActions 工作,我什至会很高兴,但我尝试过,但无法使其工作,但正如我提到的我是新手,所以也许我不知道更好。或者我导入这个导出的 const 存储:Module
即使你不能提供完整的答案,我也很乐意尝试你们提出的每一个建议,因为我很迷茫。
**更新:** 您可以看到关于如何使用 allAction|MutationTypes 的公认答案,只需导入它而不是子模块特定的 Action|MutationTypes 并在调用调度或提交时使用它。至于名称间距,这仍然是一个开放式主题,请随时分享。
由于答案不包括吸气剂,经过反复试验,我最终这样做了:
//./store/index.ts
import
Getters as AxiosGetters,
from '@/store/modules/axios/axios';
import
Getters as SiteSettingsGetters,
from '@/store/modules/site_settings/site_settings';
import
Getters as UserGetters
from '@/store/modules/user/user';
export interface RootGetters extends AxiosGetters, SiteSettingsGetters, UserGetters
//./some-store/module.ts
import RootGetters from '@/store';
type AugmentedActionContext =
commit<K extends keyof Mutations>(key: K, payload: Parameters<Mutations[K]>[1]): ReturnType<Mutations[K]>;
getters:
[K in keyof Getters]: ReturnType<Getters[K]>;
;
rootGetters:
[K in keyof RootGetters]: ReturnType<RootGetters[K]>;
;
dispatch<K extends keyof Actions>(
key: K,
payload?: Parameters<Actions[K]>[1],
options?: DispatchOptions
): ReturnType<Actions[K]>;
& Omit<ActionContext<State, RootState>, 'commit' | 'getters' | 'dispatch' | 'rootGetters'>;
export interface Actions
[ActionTypes.doSomething](context: AugmentedActionContext): Promise<void>;
export const actions: ActionTree<State, RootState> & Actions =
[ActionTypes.doSomething]( commit, rootGetters, dispatch )
// You can now use getters From other stores, and also the mutation and action useing All(name)Types and having them typed
,
【问题讨论】:
【参考方案1】:要访问其他模块,您可以定义每个模块的动作/变异类型并像这样导入所有模块。
示例动作类型
// store/action-types.ts
import ActionTypes as rootActionTypes from "./modules/root/action-types";
import ActionTypes as authUserActionTypes from "./modules/authUser/action-types";
import ActionTypes as counterActionTypes from "./modules/counter/action-types";
export const AllActionTypes =
...authUserActionTypes,
...rootActionTypes,
...counterActionTypes,
;
在组件中你可以像这样使用。
import useStore from "../../composables/useStore";
import AllActionTypes from "../../store/action-types";
// setup()
const store = useStore();
onMounted(async () =>
await store.dispatch(AllActionTypes.GET_USERS).catch((e) =>
console.log(e);
);
await store.dispatch(AllActionTypes.GET_COUNT).catch((e) =>
console.log(e);
);
);
对于您的第二个问题,这就是我一直在命名空间的方式。
// store/index.ts
import createStore from "vuex";
import IRootState from "./interfaces";
import AuthUserStoreModuleTypes from "./modules/authUser/types";
import CounterStoreModuleTypes from "./modules/counter/types";
import RootStoreModuleTypes from "./modules/root/types";
// all the modules are registered in the root
import root from "./modules/root";
export const store = createStore<IRootState>(root);
// namespacing
type StoreModules =
counter: CounterStoreModuleTypes;
root: RootStoreModuleTypes;
authUser: AuthUserStoreModuleTypes;
;
export type Store = CounterStoreModuleTypes<Pick<StoreModules, "counter">> &
RootStoreModuleTypes<Pick<StoreModules, "root">> &
AuthUserStoreModuleTypes<Pick<StoreModules, "authUser">>;
【讨论】:
太棒了,这看起来很棒,我还有一个问题,因为你的答案没有涵盖它,getter 如何在全球范围内访问?此外,您已经向我展示了在组件中使用的 allActionTypes 的示例,但这并不是一个如此胖的问题,而是我如何在其他商店中使用它们。这也适用于吸气剂?以上是关于如何在 Vuex 4 和 TypeScript 中使用其他存储模块 getter/actions/mutations的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 vuex 和 typescript 将 axios 调用移动到自己的方法中
使用 vuex 时如何在 typescript 语法中使用 mapState 函数?
Typescript Vuex - 如何使用 setter 和 getter 定义状态?
如何在单独的非 Vue 组件、JavaScript/TypeScript 文件中访问 Vuex 状态?