Vuex - 突变后获得状态

时间:2018-06-06 20:49:59

标签: javascript vue.js vuejs2 vuex

我对国家管理非常陌生。我目前正在构建具有无限加载功能的产品列表。这些是我的代码:

这是我的组成部分:

<template>
  <div class="">
    <section class="space--sm">
      <div class="container">
          <div class="row">
              <div class="col-sm-12">
                    <div v-for="(data, index) in products" v-bind:key="data.id" class="item col-sm-4 col-xs-12" :id="'data-id-'+data.id" >
                        <a href="#" v-on:click.prevent="selectProduct(data)" >
                            <h4>{{data.name}}</h4>
                        </a>
                    </div>
                    <infinite-loading force-use-infinite-wrapper="true" @infinite="infiniteHandler" ref="infiniteLoading">
                        <span slot="no-results">
                            No results
                        </span>
                        <span slot="no-more">
                            There are no more results
                        </span>
                    </infinite-loading>
                </div>
          </div>
      </div>
    </section>
  </div>
</template>

<script>
import InfiniteLoading from 'vue-infinite-loading';
import { mapState, mapActions } from 'vuex';
export default {
    name: 'List',
    computed: mapState({
        products: state => state.list.products
    }),
    methods: {
        ...mapActions('list', [
            'selectProduct'
        ]),
        infiniteHandler($state) {
            setTimeout(() => {
                this.$store.dispatch('products/fetch')

                console.log(this.products.length); 
                //returns 0 but vue debugger says products state got datas

                if (this.products.length) {
                    $state.loaded();
                    if(this.products.length < 15){
                        $state.complete();
                    }
                } else {
                    $state.complete();
                }
            }, 1000);
        },
    },
    components: {
        InfiniteLoading
    }
}
</script>

这是我的商店:

import axios from 'axios';

// initial state
const state = {
    products: [],
    selected_product: [],
    page: 1
}

// getters
const getters = {}

// mutations
const mutations = {
    FETCH(state, products) {
        state.products = state.products.concat(products);
    },
    selectProduct (state, { product }) {
        state.selected_product = product;
    },
    updatePage (state) {
        state.page += 1;
    },
}

// actions
const actions = {
    fetch({ commit }) {
        return axios.get('/api/get/products', {
            params: {
                page: state.page
            }
        })
        .then((response) => {
            commit('updatePage')
            commit('FETCH', response.data.data)
        })
        .catch();
    },
    selectProduct ({ state, commit }, product) {
        commit('selectProduct', { product })
    }
}

export default {
    namespaced: true,
    state,
    getters,
    actions,
    mutations
}

在infiniteHandler方法中,我这样做了:

this.$store.dispatch('products/fetch')

Afer变异产品状态应该已经加载了数据(使用vue调试器检查)但是当我在调度后执行此操作时: -

console.log(this.products.length);

我得到 0 ,这也意味着状态中没有数据。我做错了吗?这也是使用Vuex的最佳做法吗?谢谢

3 个答案:

答案 0 :(得分:1)

this.$store.dispatch('products/fetch')是异步的。在行动结束之前调用console.log(this.products.length);

在这种情况下,您应该使用watch

   watch: {
      products: function (newVal) {
        if (newVal.length) {
          $state.loaded();
          if(newVal.length < 15){
            $state.complete();
          }
        } else {
          $state.complete();
        }
      }
    }

答案 1 :(得分:1)

如果异步操作返回一个promise(就像你的那样),它会被dispatch的调用返回,这样你的消费者就可以等待操作完成了。

例如

async infiniteHandler($state) { // note, this is an "async" function
  setTimeout(() => {
    await this.$store.dispatch('products/fetch') // note the "await"

    console.log(this.products.length); 

    if (this.products.length) {
      $state.loaded();
      if(this.products.length < 15){
        $state.complete();
      }
    } else {
      $state.complete();
    }
  }, 1000);
},

还有一件事, fetch 操作结束时的catch()不会对您有所帮助。我建议删除它,以便让消费者知道任何错误。那,或处理你的行动中的错误,但仍然将承诺拒绝传递给你的组件,例如

.catch(res => {
  // handle error, maybe with your state
  throw res // make sure to keep rejecting the promise
})

并在您的组件中

try {
  await this.$store.dispatch('products/fetch') 
  // etc
} catch (e) {
  // do something else
}

注意到另一件事......你应该在你的行动中使用传入的上下文 state,而不是一些全局state对象,即

fetch({ state, commit }) {

答案 2 :(得分:0)

async infiniteHandler($state) { 
  setTimeout(() => {
    await this.$store.dispatch('products/fetch') 

    console.log(this.products.length); 

    if (this.products.length) {
      setTimeout(() => {
             $state.loaded();
      }, 1000);
      if(this.products.length < 15){
        $state.complete();
      }
    } else {
      $state.complete();
    }
  }, 1000);
},