Vue.js context binding in plugin?

I am trying to create a simple plugin in Vue.js to wrap a vue-resource plugin to track the status 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 that I am passing the ctx context from the calling Vue in order to access the data from them. I saw with the vue-resource plugin that there is a way to automatically bind this through the plugin bit, which cannot get the correct syntax.

Basically, I would like to avoid passing the ctx context at any given time, it should only have the appropriate context.

EDIT

To clarify, I am looking for a solution to convey the right context. The above example is just an example, and I am not looking for a solution for state tracking.

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

Context already exists in the callback. I do not need to do any var _this = this in order to get into the var _this = this . I want to achieve the same for my plugin so that the correct this there. I am trying to figure this out from the vue-resource plugin, but have difficulty following all the code.

+5
source share
2 answers

I ended up taking it apart, it was easier than I thought.

This is just a simple shortcut wrapper around the $http method in vue-router , so calls can be made like this:

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

You can check the snippet on gihub here

+1
source

Extending my comment to the answer -

So, do you have a name property on your Vue component, and you want this plugin to update this value as the HTTP request progresses? I think this gives you a bad chain of responsibility. Your Vue instance must have a name property, and your plugin will not be standalone.

It would be better to make the plugin handle all state tracking on its own. You can create a State property called status that will update as the request progresses. Then you can find out the current state using this.$state.status . Then the plugin is responsible for this, and the component 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 want to do something your own way, I think you just need to bind this to post() every time from your Vue component:

 this.$state.post(args){ }.bind(this) 

So inside post this function will be your Vue. I think the best way is best

Edit -

The successCb and errorCb already executed in the scope of the Vue component because you defined them there. The vue-resource callbacks in your situation have a State scope, because you defined them here, this will not change unless you pass the context as you did. But the point here is that your plugin does not need to know the context of the component, since vue-resource never knows the context of the component. It just receives the data, sends a request and launches a callback. Never knows anything about the calling component.

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

edit 2:

you could even have the variable $state.response and go into myCustomVar and then track $state.response.myCustomVar . Thus, you can pass different user variables for each request and track them yourself

+3
source

Source: https://habr.com/ru/post/1245372/


All Articles