【问题标题】:Parametized getter in Vuex - trigger udpateVuex 中的参数化 getter - 触发器更新
【发布时间】:2018-09-03 11:08:48
【问题描述】:

我的 Vuex 商店有一个数据集合,比如 1,000 条记录。有一个带参数的getter,getItem,获取一个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) 数据未加载,因此请稍候

【问题讨论】:

  • 如果您可以发布一些代码,将会非常有帮助。
  • 认为它更具概念性,但公平地说,我添加了商店代码和一个组件,并删除了一些不相关的代码。
  • 一切都好,如果我不说别人会说的话。堆栈溢出针对特定的代码问题和答案(尽管并不总是以这种方式结束)。Stack Exchange 上的软件工程更适合解决概念问题。 softwareengineering.stackexchange.com 但是感谢您添加代码示例! (在这些情况下也可以使用伪代码)。

标签: vuejs2 vuex


【解决方案1】:

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

state.posts[ post.slug ] = post

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

您需要像这样使用 Vue 设置:

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

欲了解更多信息,请参阅Change Detection Caveats documentation

【讨论】:

    【解决方案2】:

    抱歉,我无法使用代码来说明我的想法,因为目前还没有运行代码 sn-p。我认为你需要做的是:

    1. 在计算属性中使用 mapGetters 访问 vuex 存储,您已经在 Post.vue 中这样做了。
    2. Watch 组件内的映射 getters 属性,在您的情况下,将有一个关于 postsLandedpost 的观察器函数,无论您关心其值的变化。您可能还需要deepimmediate 属性,请查看API
    3. 通过操作触发对 vuex 存储的突变,从而改变你的 getter 将获得的存储值。
    4. watched 属性值改变后,对应的 watch 函数会被新旧值触发,你可以在那里完成你的逻辑。

    【讨论】:

      【解决方案3】:

      马克答案的代码示例

      computed: {
              ...mapGetters([
                  'customerData',
              ])
      },
      methods: {
          ...mapActions(['customerGetRecords']),
      },
      created() {
          this.customerGetRecords({
              url: this.currentData
          });
      

      【讨论】:

      • 如果你能提供一个解决方案的小文章会很好
      猜你喜欢
      • 2019-08-06
      • 2017-04-13
      • 2018-05-07
      • 1970-01-01
      • 2017-12-24
      • 1970-01-01
      • 2021-09-06
      • 2021-11-05
      • 2019-06-11
      相关资源
      最近更新 更多