首页 文章

Vuex访问状态BEFORE异步操作完成

提问于
浏览
3

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

Problem

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

Code structure

  • 组件A加载API数据 .

  • 用户点击1个数据 .

  • 组件A将单击的数据(对象)调度到组件B.

  • 组件B加载收到的对象 .

Note

DOM渲染很好 . 这是一个CONSOLE ERROR . Vue一直在关注DOM的变化并立即重新渲染 . 然而,控制台拿起一切 .

Goal

在组件A的分派完成之前,防止组件B(仅称为AFTER组件)运行其计算的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".

Question

Vuex是关于状态观察和管理的,所以如何防止此控制台错误?

提前致谢 .

3 回答

  • 0

    初始化你的州 . 与所有其他Vue数据一样,最好在起始点初始化它,即使是空 ''[] 但是VueJS(不确定Angular或React的行为是否相同,但我认为类似)将会更好地使用ALL OF您的变量已初始化 .

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

    您会发现这不仅对此有帮助,而且例如使用表单验证,因为大多数插件可以正常使用初始化数据,但无法正常使用非初始化数据 .

    希望能帮助到你 .

  • 1

    store.dispatch 可以处理触发的动作处理程序返回的Promise,它也返回Promise . 见Composing Actions .

    您可以设置 selected 操作以返回这样的承诺:

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

    然后在 SearchResults.vue 而不是使用 router-link 使用一个按钮并在 selected 动作的承诺的成功回调中执行programmatic navigation,如下所示:

    <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>
    
  • 3

    如果没有搜索结果,您可以尝试使用v-if来避免渲染模板

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

相关问题