[英]When to Use vm. or this. in Vue.js
關於何時在vue.js中使用“this”這個詞,我有點困惑。 例如,在下面的代碼中我使用“vm”而不是“this”代碼不起作用。
我也看過一些使用“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;
}
},
})
通常,在Vue中使用內部方法或計算屬性或生命周期處理程序,您將使用this
來引用方法/計算/處理程序所附加的組件。 this
指的是函數當前正在執行的上下文。
使用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
})
}
在上面的代碼中,第一個注釋可以替換為使用this
來獲取數據屬性或調用Vue( this.tickets
)方法的this.tickets
。 然而,第二條評論是在一個新的函數上下文中, this
不會引用Vue。 這是因為在Javascript中使用function() {}
語法聲明一個新函數時,該函數有自己的函數上下文,它與聲明它的函數不同 。
有幾種方法可以在Javascript中處理這個問題。 最常見的這些天,其一是使用閉包來捕捉正確的this
,或者用一個箭頭的功能。 考慮以下代碼:
AddTicket: function () {
// As before, "this" here is the Vue
axios.post('/api/Tickets', ...)
.then((response) => {
// "this" HERE is ALSO the Vue
})
}
請注意,在此示例中,使用箭頭函數( () => {}
)定義回調。 箭頭函數不會創建自己的函數上下文並使用聲明它們的上下文。 這也被稱為具有詞法范圍。
另一個最常見的解決方法是使用閉包。
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
})
}
最后,您可以使用綁定的方法來創建具有特定功能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
}
在幾乎所有情況下,你真的應該在你的問題中做你做的事情,這是在變量vm
保存對Vue的引用,並在Vue對象本身內使用該變量。 這是一個不好的做法。
在任何情況下,如何使用正確的this
一點在整個互聯網的許多帖子中都有詳細介紹, 這里也是StackOverflow 。
最后,這里是從修訂使得問題的代碼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;
}
},
})
最后,很簡單。 在您不完全了解其工作原理之前,請遵循以下簡單規則:
使用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
切勿在引用的對象本身內使用引用名稱。 在Vue對象之外,您沒有其他選擇,您只需使用引用名稱。
在Vue內部, this
內容可能會有所不同。 還會。 它只是在每個函數/對象中自動創建的另一個對象。 所以你需要這個第二條規則:在你潛入嵌套的二級函數之前,將this
保存到reference / variable。 為什么:
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.
})
}
})
如上所述,每個函數都獲得它自己的this
對象。 因此,使用'this.something = false',您只需在嵌套的二級函數中在'this'對象中創建新屬性'something',而不是在第一級函數中更改'this'。 換句話說,在嵌套函數,你失去了參考以往this
從第一級的功能,因為它的內容與在嵌套函數創建的過程中新創建的內容overwrited。 因此,如果您需要在嵌套函數中使用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
})
}
})
如您所見,您可以以任何名稱保存它。 但請遵循方便並將其命名為self
。 不是vm
,因為這個名字會再次讓你感到困惑,是否會與var vm = new Vue()
發生沖突。 它不會,但不會混淆自己,只是將其命名為self
。
不試用箭頭函數,不要使用bind。 只需按照這個簡單的規則。 之后,你會更有經驗,你可以(並且應該)使用它們,但是現在,享受編碼,而不是調試:)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.