我对State Management非常陌生。我目前正在构建一个具有无限加载功能的产品列表。以下是我的代码:
这是我的组件:
<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')在突变产品状态中应该已经加载了数据(使用vue调试器检查),但当我在分派后执行此操作时:-
console.log(this.products.length);我得到了,这也意味着状态中没有数据。我做错什么了吗?这也是使用Vuex的最佳实践吗?谢谢
发布于 2018-06-07 08:38:48
如果一个异步操作返回一个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()不会给你带来任何好处。我建议删除它,这样你的消费者就可以意识到任何错误。或者处理操作中的错误,但仍然将promise rejection传递给组件,例如
.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 }) {发布于 2018-06-07 07:13:29
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();
}
}
}发布于 2020-01-05 10:18:36
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);
},https://stackoverflow.com/questions/50729383
复制相似问题