我正在使用 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 clashes in namings
// namespaced: true,
};
//#endregion Store Type & Module
现在正如你所见,这让我重复了很多很多东西,但是在 Vuex 5 之前我不知道是否还有其他更好的解决方案。我对 TypeScript 也很陌生,我只是使用这个样板作为模板来让我的商店打字。
我的主要问题是:
- 我如何访问特定模块中的其他模块的 getter 或动作或突变,如果我能让 RootGetters 和 RootActions 工作,我什至会很高兴,但我尝试过,但我无法让它工作,但正如我提到的那样,我是一个新的对此,所以也许我不知道更好。或者我导入这个导出的 const store: Module<State, RootState> ... 就那么容易,这会使我的代码变得笨拙,因为当我想使用来自 4 个不同模块的 getter 时,我需要导入所有 4 个模块?
- 我怎样才能使这些模块命名空间,我有一些相当大的商店,谈论像 500 行和很多东西,所以没有名字冲突会很好吗?也许这会使它们更容易在其他模块中使用?
即使您无法提供完整的答案,我也很乐意尝试你们提出的每一个建议,因为我很迷茫。
**更新:**您可以看到关于如何使用 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
},