Vuex 在异步操作完成之前访问状态

Vuex accessing state BEFORE async action is complete

我遇到了计算 getter 在更新之前访问状态的问题,从而呈现旧状态。我已经尝试了一些事情,例如将突变与动作合并并将状态更改为许多不同的值,但是 getter 在调度完成之前仍在被调用。

问题

在异步操作(api 调用)完成之前访问状态。

代码结构

  1. 组件 A 加载 API 数据。
  2. 用户点击了 1 个数据。
  3. 组件 A 将点击数据(对象)分派给组件 B。
  4. 组件 B 加载接收到的对象。

备注

DOM 渲染良好。这是一个控制台错误。 Vue 一直在观察 DOM 变化并立即重新渲染。然而,控制台会拾取所有内容。

目标

在组件 A 的分派完成之前,阻止组件 B(仅在组件之后调用)运行 其计算的 getter 方法。

Store.js

import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios';

Vue.use(Vuex);

export const store = new Vuex.Store({

  state: {
    searchResult: {},
    selected: null,
  },

  getters: {
    searchResult: state => {
      return state.searchResult;
    },
    selected: state => {
      return state.selected;
    },
  },

  mutations:{
    search: (state, payload) => {
      state.searchResult = payload;
    },
    selected: (state, payload) => {
      state.selected = payload;
    },
  },

  actions: {
    search: ({commit}) => {
      axios.get('http://api.tvmaze.com/search/shows?q=batman')
        .then(response => {
          commit('search', response.data);
        }, error => {
          console.log(error);
        });
    },

    selected: ({commit}, payload) => {
      commit('selected', payload);
    },
  },

});

SearchResult.vue

<template>
<div>
  //looped
  <router-link to="ShowDetails" @click.native="selected(Object)"> 
      <p>{{Object}}</p>
  </router-link>
</div>
</template>

<script>
export default {
  methods: {
    selected(show){
      this.$store.dispatch('selected', show);
    },
  },
}
</script>

ShowDetails.vue

<template>
<div>
  <p>{{Object.name}}</p>
  <p>{{Object.genres}}</p>
</div>
</template>

<script>
export default {
  computed:{
    show(){
      return this.$store.getters.selected;
    },
  },
}
</script>

This image shows that the computed method "show" in file 'ShowDetails' runs before the state is updated (which happens BEFORE the "show" computed method. Then, once it is updated, you can see the 2nd console "TEST" which is now actually populated with an object, a few ms after the first console "TEST".

问题

Vuex 完全是关于状态监视和管理的,所以我怎样才能防止这个控制台错误?

提前致谢。

初始化你的状态。 与所有其他 Vue 数据一样,最好在起点初始化它,即使 ''[] 为空,但 VueJS(不确定 Angular 或 React 是否相同,但我想类似)在初始化所有变量后会表现得更好。

您可以在商店实例中定义状态的初始空值。

您会发现这不仅在这里很有帮助,而且例如使用表单验证,因为大多数插件都可以使用初始化数据,但不能正确使用非初始化数据。

希望对您有所帮助。

你可以尝试使用v-if来避免在没有搜索结果的情况下渲染模板

v-if="$store.getters.searchResult"

store.dispatch 可以处理触发操作处理程序 return 的 Promise,它也可以处理 return 的 Promise。参见 Composing Actions

您可以将 selected 操作设置为 return 这样的承诺:

selected: ({commit}, payload) => {
    return new Promise((resolve, reject) => {
        commit('selected', payload);
    });
} 

然后在您的 SearchResults.vue 中而不是使用 router-link 使用按钮并在 [= 的成功回调中执行 programmatic navigation 22=]selected 行动的承诺是这样的:

<template>
<div>
  //looped
  <button @click.native="selected(Object)"> 
      <p>{{Object}}</p>
  </button>
</div>
</template>

<script>
export default {
  methods: {
    selected(show){
      this.$store.dispatch('selected', show)
          .then(() => {
            this.$router.push('ShowDetails');
        });
    },
  },
}
</script>