2017-06-20 46 views
1

我遇到问题,计算得到的getter在更新之前访问状态,从而呈现旧状态。我已经尝试了一些东西,比如将突变与动作合并,并将状态更改为许多不同的值,但是在调度完成之前仍然调用getter。Vuex访问状态BEFORE异步操作完成

问题

国家是异步操作(API调用)访问之前完成。

代码结构

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

注意

的DOM渲染罚款。这是一个CONSOLE错误。 Vue一直在观察DOM更改并立即重新渲染。然而控制台拿起一切。

目标

防止组分B从运行其计算getter方法之前组分A的调度完成时(其仅称为组件之后)。

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是所有关于状态观察和管理,我怎么能防止这种控制台错误?

在此先感谢。

回答

1

store.dispatch可以处理无极返回被触发的操作处理程序,它也返回承诺。请参阅Composing Actions

你可以设置你的选择行动来回报这样一个承诺:

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

然后在你的SearchResults.vue而是采用了router-link使用按钮,并在成功回调执行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> 
0

初始化您的状态。 和所有其他Vue的数据一样,在起始点初始化它总是更好,即使是空的''[],但VueJS(不知道Angular或React的行为是否相同,但我想类似)在ALL您的变量初始化。

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

你会发现这不仅在这里有帮助,但例如,通过表单验证,因为大部分插件都可以与初始化数据一起工作,但对于非初始化数据无法正常工作。

希望它有帮助。

0

你可以尝试使用V-如果以避免渲染模板,如果它是任何搜索结果

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