首页 > 解决方案 > Vuex 中的参数化 getter - 触发 udpate

问题描述

我的 Vuex 商店有一组数据,比如 1000 条记录。有一个带有参数 getItem 的 getter,它获取一个 ID 并返回正确的记录。

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

然而,由于它是一个参数化的 getter,Vue 不会监视它所依赖的状态以了解何时更新它。我应该怎么办?

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

我觉得我需要以某种方式发出一个触发器让 getter 重新计算。

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) 数据未加载,因此请稍候

标签: vuejs2vuex

解决方案


我怀疑问题在于您如何在 storePosts 突变中设置帖子数组,特别是这一行:

state.posts[ post.slug ] = post

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

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

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

有关详细信息,请参阅更改检测警告文档


推荐阅读