javascript - Vue.js binding context in plugin? - Stack Overflow

I'm trying to create a simple plugin in Vue.js to wrap the vue-resource plugin to track the state

I'm trying to create a simple plugin in Vue.js to wrap the vue-resource plugin to track the state of a request.

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;

You will see I pass the ctx context from the calling Vue to get access to it's data values. I've seen with the vue-resource plugin that there is a way to automatically bind this through the plugin bat can't quite get the syntax right.

Basically I would like to avoid having to pass the ctx context in each time, it should just have the proper context already.

EDIT

To clarify I'm looking for a solution to pass the proper context in. The above is just sort of an example and I'm not looking for a solution to track states.

For example in the vue-resource plugin if we make any http request.

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

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

The context is already there in the callback. I don't need to do some kind of var _this = this to get into the views scope. I want to achieve the same for my plugin so that the proper this is just there. I'm trying to figure it out from the vue-resource plugin but having a hard time following all the code.

I'm trying to create a simple plugin in Vue.js to wrap the vue-resource plugin to track the state of a request.

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;

You will see I pass the ctx context from the calling Vue to get access to it's data values. I've seen with the vue-resource plugin that there is a way to automatically bind this through the plugin bat can't quite get the syntax right.

Basically I would like to avoid having to pass the ctx context in each time, it should just have the proper context already.

EDIT

To clarify I'm looking for a solution to pass the proper context in. The above is just sort of an example and I'm not looking for a solution to track states.

For example in the vue-resource plugin if we make any http request.

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

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

The context is already there in the callback. I don't need to do some kind of var _this = this to get into the views scope. I want to achieve the same for my plugin so that the proper this is just there. I'm trying to figure it out from the vue-resource plugin but having a hard time following all the code.

Share Improve this question edited Mar 22, 2016 at 8:14 Rob asked Mar 19, 2016 at 8:10 RobRob 11.4k22 gold badges72 silver badges114 bronze badges 1
  • So you have a name property on your Vue ponent, and you want this plugin to update that value as the HTTP request progresses? I think that gives you a bad chain of responsibility. Can you make a property of State called status that is updated? Then you could know the current state using this.$state.status? Then the plugin is responsible for it's purpose, and the ponent remains independent – Jeff Commented Mar 21, 2016 at 16:32
Add a ment  | 

2 Answers 2

Reset to default 3 +50

Expanding my ment to an answer -

So you have a name property on your Vue ponent, and you want this plugin to update that value as the HTTP request progresses? I think that gives you a bad chain of responsibility. Your Vue instance would be required to have a name property, and your plugin wouldn't be standalone.

It would be better to make the plugin handle all state-tracking on its own. You could make a property of State called status that is updated as the request progresses. Then you could know the current state using this.$state.status. Then the plugin is responsible for it's purpose, and the ponent remains independent

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;
            }
        }
    });
}

Then in 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>

If you do want to do things your way, I think you'd just need to bind this to post() each time from within your Vue ponent:

this.$state.post(args){

}.bind(this)

So within the post function this would be your Vue. I think the first way is best

Edit --

The functions successCb and errorCb are already run in the scope of the Vue ponent, because you defined them there. The vue-resource callbacks in your situation have the scope of State because you defined them here, that isn't going to change unless you pass the context in as you've done. But the point here is that your plugin should not need to know the context of the ponent, just as vue-resource never knows the context of the ponent. It just gets the data, sends the request, and runs the callback. Never knows anything about the calling ponent.

So in the functions you send to this.$state.post as callbacks, you can edit your Vue data using this.var - as you should be able to. In the callbacks you send to Vue.http.post from your State, you can edit properties on the State object - again, expected behavior. You need to make the name or status variable a part of State and then reference it as this.$state.name from within your Vue ponent to check the status.

edit 2:

you could even have a variable $state.response and pass in myCustomVar, and then track $state.response.myCustomVar. That way you could pass in different custom variables on each request and track them independently

I ended up sorting this out, it was easier than I thought.

It's just a simple shortcut wrapper around the $http method in the vue-router so that calls can be made like so:

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

Or

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

Can check out the snippet on Gihub here

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745339138a4623243.html

相关推荐

  • javascript - Vue.js binding context in plugin? - Stack Overflow

    I'm trying to create a simple plugin in Vue.js to wrap the vue-resource plugin to track the state

    6小时前
    20

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信