我有一个带有共同堆栈的简单应用程序:
-
后端服务器(Rails)
-
前端应用程序(Vue)
-
数据库(PG)
Vue应用程序使用Vuex存储库的操作从后端获取数据,如下所示:
// store/store.js
import Vue from 'vue';
import Vuex from 'vuex';
import * as MutationTypes from '@/store/mutation-types';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
investment: {},
},
mutations: {
[MutationTypes.SET_INVESTMENT_SHOW](state, investment) {
state.investment = investment;
},
},
actions: {
fetchInvestment({ commit }, id) {
InvestmentsApi.get(id).then((response) => {
commit(MutationTypes.SET_INVESTMENT_SHOW, response.data);
});
},
},
getters: {
participation: state =>
state.investment.included[0],
},
});
在我的组件的创建生命周期钩子中调用该操作,如下所示:
// components/Investment.vue
import { mapActions, mapGetters } from 'vuex';
export default {
name: 'Investment',
computed: {
...mapState(['investment']),
...mapGetters(['participation']),
},
created() {
this.fetchData(this.$route.params.id);
},
methods: mapActions({
fetchData: 'fetchInvestment',
}),
};
我在上面编写的代码中存在一个问题,我实际上在我的模板中使用计算值'参与',如下所示:
<BaseTitleGroup
:subtitle="participation.attributes.name"
title="Investissements"
/>
当然,因为我在组件渲染时使用了参与,所以我从getter方法得到了这个错误:
Error in render: "TypeError: Cannot read property '0' of undefined"
found in
---> <InvestmentSummary> at src/views/InvestmentSummary.vue
<App> at src/App.vue
<Root>
我认为有几种解决方案可以解决这个问题,我想知道哪一个是最佳实践,或者是否有更好的实践 .
-
第一个解决方案是在我的模板中放置一个v-if属性,以防止在等待数据时呈现元素
-
Con:渲染偏移(当数据存在时,元素开始渲染)?
-
Con:我必须为处理异步数据的应用程序的每个组件执行此操作,直觉上我更愿意在其他地方处理此问题(可能是商店?) .
-
渲染元素并将假数据放入商店,如"Loading..."
-
Con:当文本从加载切换到真实文本时,用户在加载页面时看到的小故障很难看 .
-
Con:当我的应用扩展时,我的商店的空版本会很难写,超级大
-
更改getter以返回初始空数据,而不是商店
-
Con:Getters变得更复杂
-
Con:那些不需要getter的数据(也许可以从州直接访问)
-
别的什么?
我正在寻找处理这种模式的最佳解决方案,即使它是上述之一,我只是不确定哪一种是最好的 . 非常感谢阅读!另外,我使用vue框架,但我认为这是关于现代javascript框架处理异步数据和渲染的一般问题 .
对不起,很长的帖子,这是一个土 beans ! (糟糕,不是9gag;))
2 回答
我不认为有最好的解决方案,只需选择一个并在任何地方使用它而不是将它们全部混合 .
v-if
但是如果你想从嵌套属性渲染数据可能会更好 -v-if="object.some.nested.property v-for="el in object.some.nested.property"
将起作用但预定义object = {}
将不会(它将抛出一个错误,some
未定义,你试图访问它) .我不会在您的示例中添加任何虚假数据,但您可以使用ES6 Classes来定义默认对象并将它们设置为默认值 . 只要您的类对象具有适当的结构(并且它在语法上也是透明的且易于理解),这也解决了上述预定义问题 .
至于第三种选择 - 将空数据提供给getter并不一定要复杂 - 只需将你的getter更改为:
如果已定义,则使用
state.investment.included[0]
,否则使用默认对象 .在Angular中,有Elvis(安全导航)操作符,它是处理 eventually 到达的反应数据的简明方法 .
如果它在Vue模板编译器中可用,那么您的模板将如下所示:
但是,Evan You说it sounds like a code smell .
试图将该评论扩展到您的上下文中,我认为这意味着 your template knows more about your data structure than your store .
template
这相当于:
store
由于getter用于提供Component(以及它的模板),我会选择增强getter .
但是如果你想要elvis功能,你可以在mixin中提供它 .