Vuex中的参数化吸气剂-触发udpate

时间:2018-09-03 11:08:49

标签: vuejs2 vuex

我的Vuex商店有一组数据,例如1,000条记录。有一个带有参数getItem的吸气剂,它带有一个ID并返回正确的记录。

我需要访问该getter的组件来知道何时数据准备就绪(何时完成所有记录的异步提取)。

但是,由于它是参数化的getter,因此Vue不会监视它依赖的状态来知道何时更新它。我该怎么办?

我一直想恢复到我在Angular中经常使用的BehaviorSubject模式,但是Vuex + rxJS对此很沉重,对吧?

我觉得我需要以某种方式发出触发信号,以使吸气剂重新计算。

store.js

import Vue from 'vue'
import Vuex from 'vuex'
import VueResource from 'vue-resource'

Vue.use(VueResource);

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    numberOfPosts : -1,
    posts : {}, //dictionary keyed on slug
    postsLoaded : false,
  },
  getters : {
    postsLoaded : function(state){
      return state.postsLoaded;
    },
    totalPosts : function(state){
      return state.numberOfPosts;
    },
    post: function( state ){
      return function(slug){
        if( state.posts.hasOwnProperty( slug ) ){
          return state.posts.slug;
        }else{
          return null;
        }
      }
    }
  },
  mutations: {
    storePosts : function(state, payload){
      state.numberOfPosts = payload.length;
      for( var post of payload ){
        state.posts[ post.slug ] = post;
      }
      state.postsLoaded = true;
    }
  },
  actions: {
    fetchPosts(context) {
      return new Promise((resolve) => {
        Vue.http.get(' {url redacted} ').then((response) => {
          context.commit('storePosts', response.body);
          resolve();
        });
      });
    }
  }
})

Post.vue

 <template>
      <div class="post">
        <h1>This is a post page for {{ $route.params.slug }}</h1>
        <div v-if="!postsLoaded">LOADING</div>
        <div v-if="postNotFound">No matching post was found.</div>
        <div v-if="postsLoaded && !postNotFound" class="post-area">
          {{ this.postData.title.rendered }}
        </div>
      </div>
    </template>

<script>
import { mapGetters } from 'vuex'

export default {
  name: 'post',
  data : function(){
    return {
      loading : true,
      postNotFound : false,
      postData : null
    }
  },
  mounted : function(){
    this.postData = this.post( this.$route.params.slug );
    if ( this.postData == null ){
      this.postNotFound = true;
    }
  },
  computed : mapGetters([
    'postsLoaded',
    'post'
  ])
}
</script>

按原样,它显示“找不到帖子”消息,因为访问getter时,数据尚未准备好。如果找不到帖子,我需要区分(a)数据已加载且没有匹配的帖子,以及(b)数据未加载所以请等待

3 个答案:

答案 0 :(得分:0)

抱歉,由于目前尚无正在运行的代码段,因此我无法使用代码来说明我的想法。我认为您需要做的是:

  1. 在计算属性中使用mapGetters访问vuex存储,您已经在Post.vue中进行过操作。
  2. Watch组件内部的映射的getters属性,在这种情况下,无论您关心其值的变化如何,都将有一个有关postsLandedpost的观察者函数。您可能还需要deepimmediate属性,请选中API
  3. 通过操作触发vuex商店的突变,从而将改变您的获取者将获得的商店的价值。
  4. 监视的属性值更改后,将使用新旧值触发相应的监视函数,您可以在此处完成逻辑。

答案 1 :(得分:0)

我怀疑问题出在您如何在storePosts突变(特别是这一行)中设置posts数组:

state.posts[ post.slug ] = post

VueJs无法跟踪该操作,因此无法知道数组已更新,因此您的getter不会更新。

相反,您需要像这样使用Vue集:

Vue.set(state.posts, post.slug, post)

有关更多信息,请参见Change Detection Caveats documentation

答案 2 :(得分:0)

标记答案的代码示例

    public static string MD5Hash(string text)
    {
        MD5 md5 = new MD5CryptoServiceProvider();

        //compute hash from the bytes of text  
        md5.ComputeHash(ASCIIEncoding.ASCII.GetBytes(text));


        //get hash result after compute it  
        byte[] result = md5.Hash;

        StringBuilder strBuilder = new StringBuilder();
        for (int i = 0; i < result.Length; i++)
        {
            //change it into 2 hexadecimal digits  
            //for each byte  
            strBuilder.Append(result[i].ToString("x2"));
        }

        return strBuilder.ToString();
    }