Vuex-module-decorator,修改动作内部的状态
Posted
技术标签:
【中文标题】Vuex-module-decorator,修改动作内部的状态【英文标题】:Vuex-module-decorator, modifying state inside an action 【发布时间】:2019-06-05 05:57:45 【问题描述】:使用 vuex-module-decorator 我有一个 authenticate
应该改变状态的操作。
@Action
public authenticate(email: string, password: string): Promise<Principal>
this.principal = null;
return authenticator
.authenticate(email, password)
.then(auth =>
const principal = new Principal(auth.username);
this.context.commit('setPrincipal', principal);
return principal;
)
.catch(error =>
this.context.commit('setError', error);
return error;
);
// mutations for error and principal
但这失败并显示以下消息:
未处理的承诺拒绝错误:“ERR_ACTION_ACCESS_UNDEFINED:您是否尝试在 @Action 中访问 this.someMutation() 或 this.someGetter? 这仅适用于动态模块。 如果不是动态使用 this.context.commit("mutationName", payload) 和 this.context.getters["getterName"]
我不明白的是它适用于@MutationAction
和async
。但是我错过了返回类型Promise<Principal>
。
@MutationAction
public async authenticate(email: string, password: string)
this.principal = null;
try
const auth = await authenticator.authenticate(email, password);
return principal: new Principal(auth.username), error: null ;
catch (ex)
const error = ex as Error;
return principal: null, error ;
--
此时我感到受阻,希望得到一些帮助来实现一个@Action
,它可以改变状态并在Promise
中返回特定类型。
【问题讨论】:
您找到解决方案了吗?我遇到了同样的错误... 嗨,道格拉斯。不,不是。我仍然不能有一个@MutationAction
来返回一个键入良好的Promise
。我的解决方案是使用@MutationAction
来定义将要更改的内容“mutate=..”。我不使用返回的承诺,而是对商店的变化做出反应。好的部分是所有内容都定义在商店中。但不好的部分是组件发送的操作的效果不太清楚。
我也遇到了这样的事情。我试过 @Action(rawError: true) 没有它。我的理解是 rawError 应该解决这个问题,但对我来说它在生产中运行良好,但我在开玩笑的单元测试中遇到奇怪的错误。看来这个包没有引起太多关注
我遇到同样的错误,但仍然无法找到解决方案。 @GregVeres 有任何更新吗?
@kuba1999 我能够让代码在生产中工作,但不能在单元测试中工作,因为我相信单元测试是产品开发的重要组成部分,所以我放弃了 vuex-module-decorator .我现在正在将 chris fitz 的样板转换为 typescript 并以此为起点。
【参考方案1】:
只需将 rawError 选项添加到注释中,使其变为
@Action(rawError: true)
并且正常显示错误。这是因为库“vuex-module-decorators”包装错误所以通过这样做你将能够得到一个你可以使用的 RawError
【讨论】:
【参考方案2】:如果您愿意,可以否决这个答案,因为它没有回答所提出的具体问题。相反,我建议如果你使用 typescript,那么不要使用 vuex。过去一个月我一直在尝试学习 vue /vuex 和 typescript。我承诺的一件事是使用打字稿,因为我坚信使用打字稿的好处。我永远不会再使用原始 javascript。
如果有人从一开始就告诉我不要使用 vuex,我会在过去 4 周中节省 3 周。因此,我在这里尝试与他人分享这一见解。
关键是 Vue 3 的新 ref 实现。它是真正改变 vuex 和 typescript 游戏的东西。它使我们不必依赖 vuex 自动将状态包装在响应式中。相反,我们可以自己使用 vue 3 中的 ref 构造来做到这一点。这是我的应用程序中的一个小示例,它使用了 ref 和一个 typescript 类,我过去希望在其中使用 vuex。
注意 1:使用这种方法时你会失去的一件事是 vuex 开发工具。 注意 2:我可能有偏见,因为我将 25,000 行 typescript(包含 7000 个单元测试)从 Knockout.js 移植到 Vue。 Knockout.js 就是提供 Observables(Vue 的 ref)和绑定。回想起来,它有点超前了,但没有得到追随和支持。
好的,让我们创建一个不使用 vuex 的 vuex 模块类。把它放在 appStore.ts 中。为简化起见,它将仅包含用户信息和用户登录的俱乐部 ID。用户可以切换俱乐部,因此有一个操作可以做到这一点。
export class AppClass
public loaded: Ref<boolean>;
public userId: Ref<number>;
public userFirstName: Ref<string>;
public userLastName: Ref<string>;
// Getters are computed if you want to use them in components
public userName: Ref<string>;
constructor()
this.loaded = ref(false);
initializeFromServer()
.then(info: SomeTypeWithSettingsFromServer) =>
this.userId = ref(info.userId);
this.userFirstName = ref(info.userFirstName);
this.userLastName = ref(info.userLastName);
this.userName = computed<string>(() =>
return this.userFirstName.value + ' ' + this.userLastName.value;
.catch(/* do some error handling here */);
private initializeFromServer(): Promise<SomeTypeWithSettingsFromServer>
return axios.get('url').then((response) => response.data);
// This is a getter that you don't need to be reactive
public fullName(): string
return this.userFirstName.value + ' ' + this.userLastName.value;
public switchToClub(clubId: number): Promise<any>
return axios.post('switch url')
.then((data: clubInfo) =>
// do some processing here
.catch(// do some error handling here);
export appModule = new AppClass();
然后当你想在任何地方访问 appModule 时,你最终会这样做:
import appModule from 'AppStore';
...
if (appModule.loaded.value)
const userName = appModule.fullName();
或者在基于 compositionApi 的组件中。这将取代 mapActions 等。
<script lang="ts">
import defineComponent from '@vue/composition-api';
import appModule from '@/store/appStore';
import footer from './footer/footer.vue';
export default defineComponent(
name: 'App',
components: sfooter: footer ,
props: ,
setup()
return ...appModule
);
</script>
现在您可以在模板中使用 userId、userFirstName、userName 等。
希望对您有所帮助。
我刚刚添加了计算的 getter。我需要测试是否真的需要。可能不需要它,因为您可能只能在模板中引用 fullName() 并且由于 fullName() 引用了其他 refs 的 .value 变量,所以 fullName 本身可能成为引用。但我必须先检查一下。
【讨论】:
以上是关于Vuex-module-decorator,修改动作内部的状态的主要内容,如果未能解决你的问题,请参考以下文章