我对国家管理非常陌生。我目前正在构建具有无限加载功能的产品列表。这些是我的代码:
这是我的组成部分:
<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的最佳做法吗?谢谢
答案 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);
},