Vuex: 如何在组件中监听action的回调

Created on 25 Jul 2016  ·  9Comments  ·  Source: vuejs/vuex

一个比较常见的需求,在一个组件中通过action来获取数据,这时候显示loading加载。但是vuex的理念的单向数据流,所以组件内无法获知http请求的回调,也就无法获知何时关闭loading的显示。
于是我想到两种解决方案。

方法1:
通过$watch请求的数据,来得知回调的时机。从而在watch这个钩子中来关闭loading。代码如下:

export default {
    route: {
        data (transition) {
            this.getOrderList();
            this.loading = true
        }
    },
    vuex: {
        getters: {
            orders: ({orderList}) => orderList.orders,
        },
        actions: {
            getOrderList
        }
    },
   watch: {
        'orders'() {
            this.loading = false
        }
    }
}

方法2:
在orders这个module的state中添加一个控制loading显示与否的bool字段。也就是在mutation修改orders这个state的时候把这个bool字段也进行取反赋值。这个就不贴代码了。

但是两种方法个人觉得都不是太优雅,方法1用$watch好像画蛇添足,方法2在state中添加与view相关的字段也不太合理。

所以想请教下这两种做法是否可取或者有更好的方法来实现这个需求?(还有一个想法是在route的data钩子里返回一个Promise,但是这样需要把aciton改造成一个Promise,不是很了解这种方法的实现。)

Most helpful comment

All 9 comments

action返回promise是正确的做法

@fnlctrl 能否简单给个示例代码看下,非常感谢!

 route: {
        data (transition) {
            this.getOrderList().then(() => {
              // Do something here

              // Finally call
              transition.next()
            })
        }
    },

@fnlctrl 恩这边我清楚的,我指的是getOrderList()这个action方法中应该如何返回promise?

@fnlctrl @yyx990803 问题已经解决,非常感谢,但是还是有一些疑问。
1、如果用了promise返回请求结果,那么在组件内就可以获取到data和error信息了,是否和vuex的单向数据流有冲突?
2、我现在的请求回调之后的界面提醒也是做在action中,也就是下面代码中的showMsg(),还是说通过promise在组件内的回调结果在组件内进行界面提醒。哪种方式更合理?

export const getOrderList = (store, status) => {
    var promise = new Promise(function(resolve, reject) {
        Vue.http({
            url: API_ROOT + 'orders?status=' + status,
            method: 'GET'
        }).then(function(response) {
            // success callback
            if (!response.ok) {
                store.dispatch(types.GET_ORDERLIST_FAILURE);
                showMsg(store, { content: '订单数据加载失败', type: 'warn' })
                return reject(error);
            }
            store.dispatch(types.GET_ORDERLIST_SUCCESS, { data: response.data, status: status });
            return resolve(response.data);
        }, function(error) {
            store.dispatch(types.GET_ORDERLIST_FAILURE);            
            showMsg(store, { content: '订单数据加载失败', type: 'warn' })
            return reject(error);
        });
    })
    return promise;
}

1.不冲突
2.个人倾向于在组件内做而不在store内做,因为store不应该关心UI的事情。

学习

react 的dva框架倒是有个dva-loading就是个全局的监控effects(effects对应vuex的action)是否进行中状态的map插件
希望vuex也出个类似的

Was this page helpful?
0 / 5 - 0 ratings