ger*_*s.b 5 vue.js vuex vuex-modules
使用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
Run Code Online (Sandbox Code Playgroud)
但这失败,并显示以下消息:
未处理的承诺拒绝错误:“ ERR_ACTION_ACCESS_UNDEFINED:您是否要尝试在@Action中访问this.someMutation()或this.someGetter?仅在动态模块中有效。如果不是动态的,请使用this.context.commit(” mutationName“,有效负载)和this.context.getters [“ getterName”]
我不明白的是,它与@MutationAction
and 一起使用效果很好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 };
}
}
Run Code Online (Sandbox Code Playgroud)
-
目前,我感到受阻,并希望获得一些帮助来实现一个@Action
可以改变状态并在中返回特定类型的Promise
。
只需在注释中添加 rawError 选项,它就会变成
@Action({rawError: true})
Run Code Online (Sandbox Code Playgroud)
并且它正常显示错误。这是因为库“vuex-module-decorators”包装了错误,因此通过这样做,您将能够获得可以使用的 RawError
如果您愿意,您可以否决此答案,因为它没有回答提出的具体问题。相反,我建议如果您使用的是 typescript,则不要使用 vuex。过去一个月我一直在努力学习 vue /vuex 和 typescript。我承诺的一件事是使用打字稿,因为我坚信使用打字稿的好处。我永远不会再使用原始 javascript。
如果有人从一开始就告诉我不要使用 vuex,我会在过去 4 周中节省 3 周。所以我在这里尝试与其他人分享这种见解。
关键是 Vue 3 的新 ref 实现。它真正改变了 vuex 和 typescript 的游戏规则。它使我们不必依赖 vuex 自动将状态包装在反应式中。相反,我们可以使用 vue 3 中的 ref 构造自己来做到这一点。这是我的应用程序中的一个小示例,它使用了 ref 和一个 typescript 类,我过去希望在其中使用 vuex。
NOTE1:使用这种方法时你失去的一件事是 vuex 开发工具。注意 2:我可能有偏见,因为我将 25,000 行打字稿(带有 7000 个单元测试)从 Knockout.js 移植到 Vue。Knockout.js 就是提供 Observables(Vue 的参考)和绑定。回想起来,它有点超前于它的时代,但它没有得到追随和支持。
好的,让我们创建一个不使用 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();
Run Code Online (Sandbox Code Playgroud)
然后当你想在任何地方访问 appModule 时,你最终会这样做:
import { appModule } from 'AppStore';
...
if (appModule.loaded.value) {
const userName = appModule.fullName();
}
Run Code Online (Sandbox Code Playgroud)
或在基于 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>
Run Code Online (Sandbox Code Playgroud)
现在您可以在模板中使用 userId、userFirstName、userName 等。
希望有帮助。
我刚刚添加了计算得到的 getter。我需要测试是否真的需要。可能不需要它,因为您可能只能在模板中引用 fullName() 并且 fullName() 引用其他引用的 .value 变量, fullName 可能会成为引用本身。但我必须先检查一下。
归档时间: |
|
查看次数: |
1238 次 |
最近记录: |