0%

Vue.js computed & watch 計算屬性與監視器

昨天介紹了 VueJs 裡常用的模板語法,今天就來介紹在我們 new Vue({ })裡面會用到到的 computed(計算屬性)和 watch(監視器)

我們可以先來看一下範例:去 codepen 看看效果

同樣的以 cdn 的方式先引入vue.js

前兩個是「姓」和「名」的輸入框inputFirst Name 和 Last Name,先在實例裡的data初始化他們的值之後,就可以在各別的inputp標籤看到它們顯示出來,現在要來進行將「姓」和「名」合併,且可以透過這些input去直接更改已經初始化的值。

合併「姓」和「名」的三個輸入框fullName則是想做到讓姓和名可綁定,並顯示在輸入框裡。
前兩個是單向改變,也就是說在「姓」和「名」的輸入會影響 Full Name1 和 Full Name2,但改變 Full Name1 和 Full Name2 時「姓」和「名」的內容不會更動。
最後一個是雙向的,也就是說無論是「姓」和「名」的輸入或是 Full Name3 裡的更動,兩邊的內容都會一起變動。
這幾個輸入框都是用v-model來綁定。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<div id="app2">
First Name :
<input type="text" placeholder="FirstName" v-model="firstName" /><br />
Last Name :
<input type="text" placeholder="LastName" v-model="lastName" /><br />

<!--fullName1是根據fistName和lastName計算產生出來的-->
Full Name1 (computed, sens unique ) :
<input type="text" placeholder="full Name1" v-model="fullName1" /><br />
<!--fullName2是根據watch監看產生出來的-->
Full Name2 (watch, deux sens) :
<input type="text" placeholder="full Name" v-model="fullName2" /><br />
Full Name3 (computed, deux sens) :
<input type="text" placeholder="full Name2" v-model="fullName3" /><br />

<!-- 顯示觀察用 -->
<p>firstName : {{ firstName }}</p>
<p>lastName : {{ lastName }}</p>
<p>fullName1 : {{ fullName1 }}</p>
<p>fullName2 : {{ fullName2 }}</p>
<p>fullName3 : {{ fullName3 }}</p>
</div>

先來說明這幾個在實例裡的屬性,這些屬性都是物件。

computed: { } 計算屬性

computed 是實例裡的一個屬性,而它的值是個物件,在物件裡可能會有:

  1. 多個方法的物件,對狀態屬性進行計算後,回傳一個新的資料, 供頁面獲取顯示。
  2. 自定義方法,一般情況下,相當是一個只能讀取的屬性,可利用 set/get 方法來實現屬性資料的計算讀取, 同時監視屬性資料的變化

如何給物件定義 get/set 屬性 ?
在建立物件時指定:·get name () {return xxx} / set name (value) {}
物件建立之後指定: Object.defineProperty(obj, age, {get(){}, set(value){}})

在頁面中使用雙大括號,將「方法名」包起來顯示計算的結果。

使用 computed 計算屬性的 get / set 方法雙向顯示和監視

剛剛說的 Full Name3 可達到互相牽動的效果,就是用 computed 計算屬性裡的兩個 callback 函式 getter/setter 來做到。
get()我們需要讀取當前屬性時呼叫。然後根據相關的資料計算並傳回當前屬性的值。
set(value) 並不像字面上的意思,比較像是「監視」,而是當屬性值發生變化呼叫 set callback 函式,然後去更新相關的屬性資料。在這裏value即代表 Full Name3 最新的屬性值。

如果是以 computed 來計算屬性產生值,就不需要在data裡初始化值。所以我們也不需要在data裡初始化 Full Name3 的值。
計算屬性 computed 有個特性,它會在第一次計算時就將結果存在快取裡, 多次讀取也只執行一次 getter 計算,以節省效能。

watch 監視器

監視器的寫法有兩種:

  1. 直接寫成實例的watch屬性物件,屬性的值為監聽的對象,值則 callback 函式,在函數內部進行計算。這個監聽屬性可包含多個屬性監視的物件,並分為一般監視和深度deep監視。
  2. 透過實例本身(vm)有的方法$watch()來監聽 $watch有兩個參數,第一個為要監聽的對象,第二參數為 callback 函式,在函數內部進行計算。
    有沒覺得這兩種寫法大同小異?

這兩種寫法的語法分別為:

1
2
3
4
5
6
7
8
9
// 1.
xxx: function(value){}
xxx : {
deep : true,
handler : fun(value)
}

// 2.
vm.$watch('xxx', function(value) {});

所有 Vue 實例的方法,如 watch ,都可以在前面加個$字號,而在實例外取得,如上面vm.$watch()的用法。

我們再來看一下完整的程式碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
const vm = new Vue({
el: '#app2',
data: {
firstName: 'A',
lastName: 'B',
fullName2: 'A-B',
},
// 計算屬性配置:值為物件
computed: {
// 什麼時候執行:初始化顯示/ 相關的data屬性資料發生變化
// 計算並回傳目前屬性的值
fullName1() {
// 計算屬性中的一個方法,方法的回傳值作為屬性值
return this.firstName + '-' + this.lastName;
},

fullName3: {
// 自定義物件,有兩個callback 函式 get, set(value)
// 什麼時候用? 當需要讀取當前屬性時呼叫。
// 用來做什麼? 根據相關的資料計算並傳回當前屬性的值
get() {
return this.firstName + '-' + this.lastName;
},
// 什麼時候用? 監視當前屬性的變化,當屬性值發生變化時呼叫。更新相關的資料屬性
// 用來做什麼? 根據相關的資料計算並傳回當前屬性的值
set(value) {
// value 是 fullName3 輸入的最新屬性值
console.log('fullName3 set()', value);
// 更新firstName和lastName
const names = value.split('-');
this.firstName = names[0];
this.lastName = names[1];
},
},
},
// 寫在vm 實例的監聽,叫配置監聽,另一種監聽方法使用vm的方法
watch: {
// 要監聽哪個屬性? 監聽變動時通知我們,使用callback 給我們最新的值
// 也可以同時監聽未變化的與變化後的值,以參數帶入 callback
firstName: function (value) {
// firstName 發生了變化
console.log('watch firstName', value);
// 更新 fullName2
this.fullName2 = value + '-' + this.lastName;
},
// 這段和下面用 vm.$watch() 寫的效果是一樣的。
// lastName: function (value) {
// this.fullName2 = this.firstName + '-' + value
// }
},
});
// 實例的方法都是以 $ 開頭 第一參數監聽對象 第二參數callback函式
vm.$watch('lastName', function (value) {
console.log('watch lastName', value);
// 更新 fullName2
this.fullName2 = this.firstName + ' ' + value;
});

有趣的 callback 解釋

callback 函式需滿足三個條件: 1.你定義的 2.你沒有呼叫 3.但最終它執行了
callback 什麼時候用? 呼叫函式的時候
用來做什麼? 計算並回傳當前屬性的值

再接再厲~

參考:
API — Vue.js
API — Vue.js