首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Vuex变异后的状态

Vuex变异后的状态
EN

Stack Overflow用户
提问于 2018-06-07 04:49:59
回答 3查看 2.1K关注 0票数 1

我对State Management非常陌生。我目前正在构建一个具有无限加载功能的产品列表。以下是我的代码:

这是我的组件:

代码语言:javascript
复制
<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>

这是我的店铺:

代码语言:javascript
复制
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方法中,我这样做:

代码语言:javascript
复制
this.$store.dispatch('products/fetch')

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

代码语言:javascript
复制
console.log(this.products.length);

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

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-06-07 08:38:48

如果一个异步操作返回一个promise (和您的一样),那么调用dispatch就会返回它,这样您的使用者就可以等待该操作完成。

例如

代码语言:javascript
复制
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()不会给你带来任何好处。我建议删除它,这样你的消费者就可以意识到任何错误。或者处理操作中的错误,但仍然将promise rejection传递给组件,例如

代码语言:javascript
复制
.catch(res => {
  // handle error, maybe with your state
  throw res // make sure to keep rejecting the promise
})

在您的组件中

代码语言:javascript
复制
try {
  await this.$store.dispatch('products/fetch') 
  // etc
} catch (e) {
  // do something else
}

我刚注意到另一件事。您应该在操作中使用传入的上下文state,而不是某个全局state对象,即

代码语言:javascript
复制
fetch({ state, commit }) {
票数 1
EN

Stack Overflow用户

发布于 2018-06-07 07:13:29

this.$store.dispatch('products/fetch')是异步的。在操作完成之前调用console.log(this.products.length);

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

代码语言:javascript
复制
   watch: {
      products: function (newVal) {
        if (newVal.length) {
          $state.loaded();
          if(newVal.length < 15){
            $state.complete();
          }
        } else {
          $state.complete();
        }
      }
    }
票数 1
EN

Stack Overflow用户

发布于 2020-01-05 10:18:36

代码语言:javascript
复制
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);
},
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50729383

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档