Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to Use vm. or this. in Vue.js

I am a little confused on when to use the "this" word in vue.js. For example, in the code below everywhere I use "vm" instead of "this" the code does not work.

I have also seen some examples using "self", however I am not a javascript guru and this is really confusing.

var vm = new Vue({         el: '#app',         data: {             tickets: [],             top: 100,             search: '',             showAdd: false,          },         mounted: function () {             this.$nextTick(function () {                 console.log('mounted');                 this.GetTickets(100);             })         },         methods: {             GetTickets: function (top) {                 axios.get('/api/Tickets', {                     params: {                         Top: top                     }                 })                     .then(function (response) {                         vm.tickets = response.data;                     })                     .catch(function (error) {                         console.log(error);                     });             },             ClearTicket: function () {                 var t = {                     "ticketSubject": '',                     "contactName": '',                     "createdAt": moment()                 }                 vm.ticket = t;                 vm.showAdd = !vm.showAdd;             },             AddTicket: function () {                 //vm.tickets.unshift(vm.ticket);                 axios.post('/api/Tickets', vm.ticket)                     .then(function (response) {                         console.log(response);                         vm.GetTickets(100);                     })                     .catch(function (error) {                         console.log(error);                     });                 vm.showAdd = false;              }         },      }) 
like image 927
SteveO Avatar asked Nov 07 '17 01:11

SteveO


People also ask

What is VM in VueJS?

A Vue instance is essentially a ViewModel as defined in the MVVM pattern, hence the variable name vm you will see throughout the docs. When you instantiate a Vue instance, you need to pass in an options object which can contain options for data, template, element to mount on, methods, lifecycle callbacks and more.

Why we use this in Vue?

The this keyword within Vue gives you easy access to all of your data and functionalities. Wether you want to access a data property, a computed property, a component prop or a function, you can all find them directly on the this keyword.

What is the difference between V show and V if directives?

v-if - Only renders the element to the DOM if the expression passes. v-show - Renders all elements to the DOM and then uses the CSS display property to hide elements if the expression fails.

What is Vue instance in VueJS?

A Vue instance uses the MVVM(Model-View-View-Model) pattern. The Vue constructor accepts a single JavaScript object called an options object. When you instantiate a Vue instance, you need to pass an options object which can contain options for data, methods, elements, templates, etc.

What is the VM variable in Vue?

As a convention, we often use the variable vm (short for ViewModel) to refer to our Vue instance. When you create a Vue instance, you pass in an options object.

How to use Vue JS?

The first thing to do in order to use Vue.js is to import it. If you follow the official guide and use an inline template for your component, you will get a blank page. Note that this issue doesn’t occur when you define templates with the render function or SFC ( Single File Component ). Actually, there are many Vue builds.

Should I name my new Vue app self or VM?

Not vm, as this name can confuse you again, whether it will collide with var vm = new Vue (), or not. It will not, but doesn't confuse yourself and just name it as self. Does not experiment with arrow functions, do not use bind.

When to use reference name in Vue object?

Use this everywhere in Vue object, and use its reference identifier outside: Never use reference name inside the referenced object itself. Outside the Vue object you have no other choice, you just must use the reference name. Inside Vue, this content may vary.


1 Answers

Typically, inside methods, or computed properties or lifecycle handlers in Vue, you will use this to refer the component to which the method/computed/handler is attached. this refers to the context in which the function is currently executing.

Where you get into trouble using this is when a new function is declared in the context of the current function, as happens when you write a callback to a promise (axios.post, axios.get). Consider this code:

AddTicket: function () {   // "this", on this line, refers to the Vue   // and you can safely use "this" to get any of the   // data properties of the Vue     axios.post('/api/Tickets', ...)       .then(function (response) {         // "this" HERE, does NOT refer to the Vue!!         // The reason why explained below                     }) } 

In the above code, the first comment could be replaced with code that uses this to get data properties or call methods of the Vue (this.tickets). The second comment, however is inside a new function context, and this will NOT refer to the Vue. This is because in Javascript when you declare a new function using the function() {} syntax, that function has its own function context which is different from the function in which it is declared.

There are several ways to deal with this in Javascript. The most common these days are to either use a closure to capture the correct this, or to use an arrow function. Consider this code:

AddTicket: function () {   // As before, "this" here is the Vue     axios.post('/api/Tickets', ...)       .then((response) => {         // "this" HERE is ALSO the Vue       }) } 

Note that in this example, the callback is defined using an arrow function (() => {}). Arrow functions do NOT create their own function context and use the context in which they are declared. This is also known as having a lexical scope.

The other most common workaround is using a closure.

AddTicket: function () {   const self = this // Here we save a reference to the "this" we want     axios.post('/api/Tickets', ...)       .then(function(response){         // and HERE, even though the context has changed, and we can't use         // "this", we can use the reference we declared (self) which *is*         // pointing to the Vue         self.tickets = response       }) } 

Finally, you can use the bind method to create a function with a specific this, though this is not as common these days with arrow functions available.

AddTicket: function () {     axios.post('/api/Tickets', ...)       .then(function(response){         this.tickets = response       }.bind(this)) // NOTE the ".bind(this)" added to the end of the function here } 

In almost no case, should you really be doing what you do in your question, which is save a reference to the Vue in the variable vm and use that variable inside the Vue object itself. That's a bad practice.

In any case, how to use the correct this is covered in detail in numerous posts throughout the internet and here on StackOverflow as well.

Finally, here is the code from the question revised such that this should be used correctly.

var vm = new Vue({   el: '#app',   data: {     tickets: [],     top: 100,     search: '',     showAdd: false,     ticket: null   },   mounted: function () {     // there is no need for $nextTick here     this.GetTickets(100)   },   methods: {     GetTickets: function (top) {       axios.get('/api/Tickets', { params: { Top: top }})         .then(response => this.tickets = response.data)         .catch(error => console.log(error));     },     ClearTicket: function () {       var t = {         "ticketSubject": '',         "contactName": '',         "createdAt": moment()       }       this.ticket = t;       this.showAdd = !this.showAdd;     },     AddTicket: function () {       axios.post('/api/Tickets', this.ticket)         .then(() => this.GetTickets(100))         .catch(error => console.log(error));        this.showAdd = false;     }   }, }) 
like image 130
Bert Avatar answered Oct 23 '22 19:10

Bert