插件中的Vue.js绑定上下文?

时间:2016-03-19 08:10:59

标签: javascript vue.js vue-resource

我试图在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;

您会看到我从调用的Vue传递ctx上下文,以便访问它的data值。我在vue-resource插件中看到有一种方法可以通过插件自动绑定它,这样就可以使语法正确。

基本上我想避免每次都要传递ctx上下文,它应该只有适当的上下文。

修改

澄清我正在寻找一种能够通过适当语境的解决方案。上面只是一个例子,我没有寻找跟踪状态的解决方案。

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

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

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

回调中已存在上下文。我不需要做某种var _this = this来进入视图范围。我想为我的插件实现相同的目的,以便正确的this就在那里。我试图从vue-resource插件中弄清楚它,但是很难跟踪所有代码。

2 个答案:

答案 0 :(得分:3)

将我的评论扩展为答案 -

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

最好让插件自己处理所有状态跟踪。您可以创建名为status的State属性,该属性随着请求的进行而更新。然后,您可以使用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组件中绑定thispost()

this.$state.post(args){

}.bind(this)

所以在post函数this中你的Vue就是。我认为第一种方式是最好的

编辑 -

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

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

编辑2:

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

答案 1 :(得分:1)

我最终对此进行了整理,这比我想象的要容易。

这只是$httpvue-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上的代码段here