5

我正在尝试在 Vue.js 中创建一个简单的插件来包装vue-resource插件以跟踪请求的状态。

function State() {}

State.prototype.post = function (ctx, name, url, data, successCB, errorCB) {
    var options = {};

    if (errorCB) {
        options.error = function (resp) {
            ctx[name] = 'error';

            return errorCB(resp);
        };
    }

    ctx[name] = 'sending';

    ctx.$http.post(url, data, function (res, code, req) {
        ctx[name] = 'sent';

        return successCB(res, code, req);
    }, options);
};

function install(Vue) {
    Object.defineProperties(Vue.prototype, {
        $state: {
            get: function () {
                return new State;
                // return Vue.state.bind({$vm: this});
            }
        }
    });
}

module.exports = install;

你会看到我ctx从调用 Vue 传递上下文来访问它的data值。我已经看到vue-resource插件有一种方法可以通过插件自动绑定它 bat 不能完全正确地获取语法。

基本上我想避免ctx每次都传递上下文,它应该已经有了正确的上下文。

编辑

为了澄清,我正在寻找一种解决方案来传递正确的上下文。上面只是一个例子,我不是在寻找跟踪状态的解决方案。

例如在vue-resource插件中,如果我们发出任何 http 请求。

this.$http.get('/some/url', {}, function () {
    this.func();

    console.log(this.var);
});

回调中已经存在上下文。我不需要做一些事情var _this = this来进入视图范围。我想为我的插件实现同样的效果,这样合适this的就在那里。我试图从vue-resource插件中找出答案,但很难遵循所有代码。

4

2 回答 2

3

将我的评论扩展到答案 -

所以你name在你的 Vue 组件上有一个属性,并且你希望这个插件随着 HTTP 请求的进行更新这个值?我认为这给了你一个糟糕的责任链。您的 Vue 实例需要有一个name属性,并且您的插件不会是独立的。

最好让插件自己处理所有状态跟踪。您可以创建一个称为 State 的属性,该属性会status随着请求的进行而更新。然后您可以使用this.$state.status. 然后插件负责它的用途,组件保持独立

State.prototype.status = "not sent"; 

State.prototype.post = function (url, data, successCB, errorCB) {
    var options = {};

    if (errorCB) {
        options.error = function (resp) {
            this.status = 'error';

            return errorCB(resp);
        };
    }

    this.status = 'sending';

    this.Vue.http.post(url, data, function (res, code, req) {
        this.status = 'sent';

        return successCB(res, code, req);
    }, options);
};

function install(Vue) {
    Object.defineProperties(Vue.prototype, {
        $state: {
            get: function () {
                var state = new State;
                state.Vue = Vue;
                return state;
            }
        }
    });
}

然后在html中:

<div v-if="$state.status == 'sending'">Sending...</div>
<div v-if="$state.status == 'sent'">Sent!</div>
<div v-if="$state.status == 'error'">Error!</div>

如果您确实想按照自己的方式做事,我认为您只需要每次都从 Vue 组件中绑定this到:post()

this.$state.post(args){

}.bind(this)

因此,post函数内this将是您的 Vue。我认为第一种方法最好

编辑 -

函数successCberrorCb已经在 Vue 组件的范围内运行,因为您在那里定义了它们。您的情况下的vue-resource回调具有范围,State因为您在此处定义了它们,除非您按照您所做的那样传递上下文,否则它不会改变。但这里的重点是你的插件不需要知道组件的上下文,就像vue-resource永远不知道组件的上下文一样。它只是获取数据、发送请求并运行回调。对调用组件一无所知。

因此,在您作为回调发送到的函数中,您可以使用-this.$state.post来编辑您的 Vue 数据,因为您应该能够使用. 在您从您的状态发送到的回调中,您可以编辑对象的属性 - 再次,预期的行为。您需要将or变量作为其中的一部分,然后在您的 Vue 组件中引用它以检查状态。this.varVue.http.postStatenamestatusStatethis.$state.name

编辑2:

你甚至可以有一个变量$state.response并传入myCustomVar,然后跟踪$state.response.myCustomVar。这样您就可以在每个请求中传递不同的自定义变量并独立跟踪它们

于 2016-03-21T16:59:47.733 回答
1

我最终解决了这个问题,这比我想象的要容易。

它只是中$http方法的一个简单快捷方式包装器,vue-router因此可以像这样进行调用:

this.$state.get('/buildings', data, function (resp) {
    this.buildings = resp.data;
}, {
    track: 'getBuildingState'
});

或者

this.$state('/buildings', {
    data: data,
    track: 'getBuildingState',
    success: function (resp) {
        this.buildings = resp.data;
    }
});

可以在这里查看 Gihub 上的片段

于 2016-03-26T04:49:40.350 回答