聊一聊 Vue 中 watch 對象中的回調函數為什么不能是箭頭函數
本文重點知識點速覽:
- Vue 中的 watch 對象中的回調函數不能是箭頭函數。
- 箭頭函數中的 this 指向的是函數定義時所在的對象,普通函數中的 this 指向的是函數運行時所在的對象。
- 函數的 this 指向問題。
一起學習吧...
說起箭頭函數大家一定不陌生,箭頭函數是 ES6 中對函數的擴展,使用起來方便快捷,可能有些小伙伴對箭頭函數不是特別了解,所以在這里先舉個例子吧。
// 普通函數定義
function add(a, b) {
return a + b;
}
// 箭頭函數等價定義
const add = (a, b) => {
return a + b;
}
// 普通匿名函數
fucntion() {
console.log('hello');
}
// 箭頭函數等價定義
() => {
console.log('hello');
}
箭頭函數在定義回調函數中使用的非常多,但是在 Vue 中的 watch 對象的回調函數中就不能使用回調函數,先看下面的例子:
代碼有一點長,簡單說明一下就不用看所有的代碼了,下面代碼實現的是實現監視數據 a 和 b 的變化,當其中一個改變時執行相應的回調函數求a與b的和,重點在 23-30 行。
下面的代碼中 watch 中回調函數是普通的函數,我們知道 對於普通函數,函數中的this指向函數運行時所在的對象。
所以,當我們在瀏覽器中改變a的值時(例如在瀏覽器的控制台輸入 vm.a = 10),代碼 23 行打印出來的是一個 Vue 對象(即代碼 14行新創建出來的vm實例),因為此時 代碼 22 行的 function 函數運行在 vm 對象中,此時頁面會發生變化,由原來的 3 變為 12.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue中的watch</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
{{sum}}
</div>
<script>
var vm = new Vue({
el: "#app",
data: {
a: 1,
b: 2,
sum: 3
},
watch: {
a: function() {
console.log(this);
this.sum = this.a + this.b;
},
b: function() {
this.sum = this.a + this.b;
}
}
})
</script>
</body>
</html>
我們再來看一下用箭頭函數當做 watch 的回調函數的情況,把代碼21-29行換成如下的代碼即可:
watch: {
a: () => {
console.log(this);
this.sum = this.a + this.b;
},
b: () => {
this.sum = this.a + this.b;
}
}
當我們這時候再在瀏覽器的控制台改變 a 的值時(比如 在控制台輸入 vm.a = 10),會發現打印出來的是 window 對象,所以頁面的內容也不會發生變化。
JS 代碼分為 預解析階段和執行階段,在預解析階段遇到函數聲明會提前進行預解析,此時下面代碼中的箭頭函數會在全局定義,因為 var vm = new Vue({...})
這句代碼在預解析階段還沒有被執行。當到了執行階段並且在控制台改變 a 的值后,watch 中的下面代碼中的箭頭函數開始執行,此時的運行環境確實是新創建的 vm 對象。但是對於箭頭函數來說,箭頭函數中的 this 指向的是定義時的對象而不是函數運行時所在的對象,這一點與普通函數有很大的區別。
a: () => {
console.log(this);
this.sum = this.a + this.b;
}
如果對於 this 的指向問題如果還不是很清楚可以參考下面的兩篇博客:
完
歡迎指正