javascript 何时使用 vm。或这个。在 Vue.js 中
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/47148363/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
When to Use vm. or this. in Vue.js
提问by SteveO
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.
我对何时在 vue.js 中使用“this”这个词感到有些困惑。例如,在下面的代码中,我到处使用“vm”而不是“this”,代码不起作用。
I have also seen some examples using "self", however I am not a javascript guru and this is really confusing.
我也看到了一些使用“self”的例子,但是我不是 javascript 专家,这真的很令人困惑。
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;
}
},
})
回答by Bert
Typically, inside methods, or computed properties or lifecycle handlers in Vue, you will use thisto refer the component to which the method/computed/handler is attached. thisrefers to the context in which the function is currently executing.
通常,在 Vue 中的方法、计算属性或生命周期处理程序中,您将使用this引用方法/计算/处理程序附加到的组件。this指的是函数当前正在执行的上下文。
Where you get into trouble using thisis 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:
当你this在当前函数的上下文中声明一个新函数时,你会遇到使用问题,就像你写一个对 promise ( axios.post, axios.get)的回调一样。考虑这个代码:
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 thisto get data properties or call methods of the Vue (this.tickets). The second comment, however is insidea new function context, and thiswill 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 differentfrom the function in which it is declared.
在上面的代码中,第一个注释可以替换为this用于获取数据属性或调用 Vue ( this.tickets)方法的代码。然而,第二条注释是在一个新的函数上下文中,this不会引用 Vue.js 文件。这是因为在 Javascript 中,当您使用function() {}语法声明一个新函数时,该函数有自己的函数上下文,这与声明它的函数不同。
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:
在 Javascript 中有几种方法可以解决这个问题。现在最常见的是使用闭包来捕获正确的this,或者使用箭头函数。考虑这个代码:
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 methodto create a function with a specific this, though this is not as common these days with arrow functions available.
最后,您可以使用bind 方法创建一个具有特定 的函数this,尽管这在现在箭头函数可用的情况下并不常见。
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 vmand use that variable insidethe Vue object itself. That's a bad practice.
在几乎任何情况下,您是否真的应该按照您在问题中所做的操作,即在变量中保存对 Vue 的引用,vm并在 Vue 对象本身内部使用该变量。这是一个不好的做法。
In any case, how to use the correct thisis covered in detail in numerous posts throughout the internetand here on StackOverflowas well.
在任何情况下,如何使用正确this的详细介绍在众多帖子整个互联网和这里在计算器上也是如此。
Finally, here is the code from the question revised such that thisshouldbe used correctly.
最后,这里是从修订这样的问题的代码this应该被正确使用。
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;
}
},
})
回答by SteveO
In the end, it is simple. Until you do not fully understand how it works, just follow these simple rules:
最后,这很简单。在您不完全理解它是如何工作的之前,只需遵循以下简单规则:
Use thiseverywhere in Vue object, and use its reference identifier outside:
this在 Vue 对象中的任何地方使用,并在外部使用其引用标识符:
var vm = new Vue({
// Use "this" inside
el: '#app',
data: {
something: true
},
created: function () {
this.something = false // like here
}
})
// Here, outside, use reference iditentifier,
// as you have no other choice
vm.something = null
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.
永远不要在引用对象本身内使用引用名称。在 Vue 对象之外,您别无选择,您只能使用引用名称。
Inside Vue, thiscontent may vary. And will. It is just another object, automatically created within each function/object. So you need this second rule: before you dive to nested, second level function, save thisto reference/variable. Why:
在 Vue 内部,this内容可能会有所不同。还会。它只是另一个对象,在每个函数/对象中自动创建。所以你需要第二条规则:在你深入到嵌套的二级函数之前,保存this到引用/变量。为什么:
var vm = new Vue({
el: '#app',
data: {
something: true
},
created: function () {
// You are in first level function,
// you can use "this"
axios.get('/uri').then(function () {
// Here you are in nested, second level
// function. It will have own "this" object
this.something = false // no error here but...
// You did not changed "something" value in data object,
// you just created new property also called "something",
// but in this nested "this" object.
})
}
})
As mentioned above, every function obtains it's own thisobject. So, with 'this.something = false' you just created new property 'something' in 'this' object in nested, second level function, instead of changing 'this' in first level function. In other words, in nested function you lost reference to previous thisfrom first level function, as it's content was overwrited with newly created content in process of nested function creation. So, if you need to use thisobject form first level function in nested function, just save it under another name, which will be not overwrited:
如上所述,每个函数都获得它自己的this对象。因此,使用“this.something = false”,您只是在嵌套的二级函数中的“this”对象中创建了新属性“something”,而不是在一级函数中更改“this”。换句话说,在嵌套函数中,您失去了对前this一级函数的引用,因为它的内容在嵌套函数创建过程中被新创建的内容覆盖。因此,如果您需要this在嵌套函数中使用对象形式的一级函数,只需将其保存为另一个名称,该名称不会被覆盖:
var vm = new Vue({
el: '#app',
data: {
something: true
},
created: function () {
var anyName = this // Save reference to this under another name
axios.get('/uri').then(function () {
this.something = false // no error here, but you are still creating new property
anyName.something = false // NOW you are really changing "something" value in data
})
}
})
As you can see, you can save it under any name. But follow the convenience and name it as self. 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.
如您所见,您可以使用任何名称保存它。但为了方便起见,将其命名为self. 不vm,因为这个名称可能会再次混淆您,无论它是否会与 发生冲突var vm = new Vue()。它不会,但不会混淆你自己,只是将其命名为self.
Does not experiment with arrow functions, do not use bind. Just follow this simple rules. Later, you will be more experienced, you can (and should) use them, but for now, enjoy the coding, not debugging :)
不试验箭头函数,不使用绑定。只需遵循这个简单的规则。稍后,您将更有经验,您可以(并且应该)使用它们,但是现在,请享受编码,而不是调试 :)

