当前位置: 首页 > 知识库问答 >
问题:

如何使用Vuex/Vue处理异步数据检索

喻渊
2023-03-14

我有一个简单的应用程序与一个共同的堆栈:

  • 后端服务器(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',
  }),
};

我上面写的代码中有一个问题,我实际上在模板中使用了计算值“participation”,如下所示:

<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属性,以防止元素在等待数据时呈现
    • 缺点:渲染偏移量(当数据存在时元素开始渲染)?
    • 缺点:我必须为我的应用程序中处理异步数据的每个组件做这件事,直觉上我更喜欢在其他地方处理这件事(也许是商店?)。
    • 缺点:当文本从加载切换到真实文本时,用户在加载页面时看到的小故障很难看
    • 缺点:当我的应用程序扩展时,我的应用商店的空版本写起来会很痛苦,而且会非常大
    • 缺点:获得者变得更加复杂
    • 缺点:不需要getter的数据(可能可以从州直接访问)如何处理

    我正在寻找处理这种模式的最佳解决方案,即使是上面提到的其中一个,我只是不确定哪一个是最好的。非常感谢您的阅读!此外,我使用vue框架,但我认为这更像是现代javascript框架处理异步数据和渲染的一般问题。

    抱歉发了这么长的帖子,这是一个土豆!(哎呀,不是在9gag;)上)

共有2个答案

何越
2023-03-14

我不认为有最好的解决方案,只要选择一个,并使用它无处不在,而不是混合所有。

v-if但是,如果您想从嵌套属性呈现数据,可能会更好-v-if="object.some.nested.propertyv-for="el inobject.some.nested.property"将工作,但预先定义对象={}不会(它会抛出一个错误,一些是未定义的,你试图访问它)。

我不会像你的例子那样放任何假数据,但是你可以使用ES6类来定义默认对象,并将它们设置为默认值。这也修复了上面的预定义问题,只要你的类对象有一个合适的结构(而且它在语法上是透明的,易于理解)。

至于第三个选项——将空数据提供给getter并不复杂——只需将getter更改为:

getters: {
    participation: state =>
      state.investment.included[0] || new DefaultParticipationObject() // I don't know what's in included array
  },

这使用状态。投资包含[0],如果已定义,则为默认对象。

李华茂
2023-03-14

在Angular中,有埃尔维斯(安全导航)运算符,这是处理最终到达的反应性数据的一种简洁方法。

如果在Vue模板编译器中可用,则您的模板将如下所示:

<BaseTitleGroup
  :subtitle="participation?.attributes?.name"
  title="Investissements"
/>

然而,埃文·尤说这听起来像是一种代码的味道。

您的模型/状态应尽可能可预测。

试图将该注释扩展到您的上下文中,我认为这意味着您的模板比您的商店更了解您的数据结构。

模板

"participation.attributes.name"

这相当于:

state.investment.included[0].attributes.name

商店

state: {
  investment: {},
},

因为getter是为组件(和它的模板)服务的,所以我会选择增强getter。

getters: {
  participation_name: state => {
    return 
      (state.investment.included 
       && state.investment.included.length
       && state.investment[0]
       && state.investment[0].attributes
       && state.investment[0].attributes.name)
      || null;
},

<BaseTitleGroup
  :subtitle="participation_name"
  title="Investissements"
/>

但是如果你想要elvis的功能,你可以在mixin中提供它。

var myMixin = {
  computed: {
    elvis: {
      get: function() {
        return (known, unknown) => {
          // use regex split to handle both properties and array indexing
          const paths = unknown.split(/[\.(\[.+\])]+/); 
          let ref = known
          paths.forEach(path => { if (ref) ref = ref[path] });
          return ref;
        }
      }
    },
  }
}

export default {
  name: 'Investment',
  ...
  mixins: [myMixin],
  computed: {
    ...mapState(['investment']),
    participation_name() {
      return this.elvis(this.investment, 'included[0].attributes.name')
    }
  },
  ...
};
 类似资料:
  • 问题内容: 我有很多关于在Android应用程序中处理异步数据库的问题。 由于我知道数据库是异步的,因此我尝试了几种方法来处理它。如您在代码中所见,我有两个函数需要在数据库中使用数组。我的第一个函数()将对数据库中的数组应用更改,而我的第二个函数()需要将此数组与从我的第一个函数中应用的更改一起使用。这是我的代码: 这是setArray_for_database的代码: 这是我的把戏。具有另一个内

  • 我正在用异步JobLauncher在Spring Batch中配置一个(长时间运行的)作业,我有两个RESTendpoint: null 谢谢朱利奥

  • 在我的Vue应用程序中,我有Vuex存储模块,它们的状态下有大量资源对象。为了方便地访问这些数组中的单个资源,我制作了Vuex getter函数,将资源或资源列表映射到各种键(例如“id”或“标签”)。这导致性能迟缓和巨大的内存占用。如何在没有如此多重复数据的情况下获得相同的功能和反应性?

  • 问题内容: 我目前正在使用node.js应用程序,并且遇到了通常的异步代码问题。 我正在Node的HTTP模块之上实现服务服务器。 该服务器支持(类似表达)路由。例如,我有如下代码: 服务器需要能够承受故障,当传递给任何函数的问题出现时,我不想使整个服务器崩溃。当我编写如下代码时,会发生问题: 我看不到如何在这里捕获错误。我不想因一个服务器端故障而使服务器崩溃,而是要服务500个。 我能够提出的唯

  • 如果组件不是和路由绑定的页面组件,原则上是不可以使用异步数据的。因为 Nuxt.js 仅仅扩展增强了页面组件的 data 方法,使得其可以支持异步数据处理。 对于非页面组件,有两种方式可以实现数据的异步获取: 在组件的 mounted 方法里面实现异步获取数据的逻辑,之后设置组件的数据,限制是:不支持服务端渲染。 在页面组件的asyncData或fetch方法中进行API调用,并将数据作为prop

  • 在Servlet 3.0中,引入了异步处理的概念。所以所有的书都说这消除了每个请求一个线程的要求。我已经测试过了,是的,它确实有效。现在,我有一个简单的servlet,用户在其中以同步模式启动HTTP请求。线程只需Hibernate1秒,然后回复客户端。当我对这种模式进行负载测试时,服务器每秒只能处理4个请求。现在,我将同步模式更改为异步模式,并根据请求创建一个新线程,将原始http线程释放回池。