# Vue - Methods vs Computed vs Watch
## Methods(方法):
#### 觸發條件:
1. 搭配 `v-on` 做事件,讓處理使用者觸發
2. 呼叫 function 並 return 值,可以做資料處理/運算...等
3. 理論上,computed 能做的 methods 都能做
#### 運作特性:
只要有資料更新,觸發重新渲染,就算
- 沒有用到此 funciton
- 依賴的資料沒有更新
也會重新運算,相對比較吃效能
#### 適用情境:
需要在重新渲染時,更新全部函數運算結果
#### 使用方法:
1. methods 本身是 vue 實例物件中的一個 **鍵值(key-value)/屬性** ,其值為一個物件
2. methods 裡面宣告的屬性都是 **function**
```javascript=
methods:{
funcName:function(){
// doSomething...
},
// 等於
funcName(){
// doSomething...
}
}
```
3. 在 `<template>` 當中需要加入小括號,當然它也可以傳入參數
```htmlmixed=
<button v-on:click="funcName(val)">
```
4. 在 methods 屬性中呼叫另一個 methods 屬性,透過 this.funcName() 即可
```javascript=
methods:{
funcOne(){
// doSomething...
},
// 等於
funcTwo(){
this.funcOne();
// doSomething...
}
}
```
## Computed(計算屬性):
#### 觸發條件:
當依賴的資料更新時, computed 就會重新計算
#### 運作特性:
- 會將計算後的結果暫存
- 若依賴的資料沒有更新的情況下,多次訪問將返回之前暫存的計算結果, computed 將不會重複執行計算
#### 適用情境:
1. 變數需要依賴其它變數更新而變動
2. 沒有特別需要每次都運算函數,那就使用 computed 效能會比較好
#### 使用方法:
1. computed 本身是 vue 實例物件中的一個**鍵值(key-value)/屬性**,其值為一個物件
2. computed 裡的屬性可以是 key-value 也可以是 function
- key-value:
- 值為**物件**,包含 return 值的 getter 與 更新依賴的 setter
- 若沒有加上 set( ) ,則手動修改其值時將發生錯誤訊息
- key-value 本身並不需要先在 <a href="#data">data</a> 中定義
</br>
```htmlmixed=
<div>{{funcName}}<div>
```
```javascript=
Vue.createApp({
data(){
return{
test:1
}
},
computed:{
// getter and setter
keyName:{
// getter
get(){
return this.test * 10;
},
// setter
set(value){
this.test = value / 10;
}
}
}
})
```
- function:
- **無法帶入參數**,並用 return 的方式回傳計算結果
- 在`<template>`當中不需要加入小括號,,直接調用即可`{{ funcName }}`
- function name 等同於 key-value 的 key ,但是用 function 的方式只會有 getter 的功能
<br>
```htmlmixed=
<div>{{keyName}}<div>
```
```javascript=
Vue.createApp({
data(){
return{
test:1
}
},
computed:{
// only getter
funcName:function(){
return this.test * 10;
}
// 等於
funcName(){
return this.test * 10;
}
}
})
```
3. 可以使用 v-model 綁定 computed 裡面宣告的 key-value ,並使用 get() 更新 object 的值、set(value) 反推回去更新其所依賴的資料
4. 在 methods 屬性中使用 computed 的屬性,透過 this.funcName 即可
:::success
<span id="data">data</span> 是 vue 實例物件中的一個 function ,並用 return key-value 的方式定義變數
:::
## Watch(監聽屬性):
#### 觸發條件:
觀察 data 或 computed 中的 key-value ,當 key-value 產生變動時,觸發相對應的處理
#### 運作特性:
1. 其允許我們執行異步操作 (訪問一個 API),限制我們執行該操作的頻率,並在我們得到最終結果前,設置中間狀態。這些都是計算屬性無法做到的。
2. 當你有一些數據需要隨著其它數據變動而變動時,你很容易濫用 watch,然而,通常更好的做法是使用 computed 而不是命令式的 watch 回調
#### 適用情境:
1. 只需要觀察 data 或 computed 內 key-value 狀態的時候
2. key-value 變化時執行**異步**或**開銷較大的操作**時
#### 使用方法:
1. watch 本身是 vue 實例物件中的一個**鍵值(key-value)/屬性**,其值為一個物件
2. watch 裡的屬性可以是 key-value 也可以是 function
- key-value
- key 定義我們想要觀察的值, value 定義相對應的操作
- 若要觀察的資料為巢狀結構,則 key 需要使用字串 'parent.child'
- value 可以是
- String:呼叫 methods 的 function
- Function:一個資料來源註冊一個監聽器
- Object :包含 handler( funciton ) 、可選設定 deep、immediate
- Array:同個資料來源註冊多個監聽器
- funciton
- function name 等同於 key-value 的 key ,也就是欲觀察的 key
- funciton 有兩個預設參數值 (**newValue**, **oldValue**) ,第一為觀察改變後的值,第二為觀察改變前的值
3. 屬性
- deep : 布林值,是否監聽物件下層屬性
- immediate : 布林值,是否在實體初始化時立即叫用 callback 函數
<br>
```javascript=
// String
Vue.createApp({
data(){
return{
test:1
}
},
watch:{
test:'funcName';
},
methods:{
funcName(){
// doSomething.....
}
}
})
```
```javascript=
// Function
Vue.createApp({
data(){
return{
test:1
}
},
watch:{
test:function(newVal, oldVal){
// doSomething
}
// 等於
test(newVal, oldVal){
//doSomething
}
}
})
```
```javascript=
// Object
Vue.createApp({
data(){
return{
test:1
}
},
watch:{
test:{
handler(newVal, oldVal){
// doSomething
},
deep: true | false,
immediate: true | false
}
}
})
```
```javascript=
// Array
Vue.createApp({
data(){
return{
test:1
}
},
watch:{
test:[
'handler1',
function handler2(newVal){
// doSomething...
},
{
handler: function handle3(newVal, oldVal){
// doSomething...
},
// ...
}
]
},
methods:{
handler1(){
// doSomething...
}
}
})
```
> https://peterhpchen.github.io/VuejsQuest/basic/08_Watcher.html#watch
:::danger
$watch
https://v3.vuejs.org/api/instance-methods.html#watch
:::
:::warning
methods、computed、watch 裡的 function 其實也是 key-value,可以寫成:
```javascript=
funcName(){.....}
// 等於
funcName:funciton(){.....}
```
<font color="red">之所以可以縮寫,是因為 JavaScript ES6 中,物件的屬性與函式縮寫(object-shorthand)</font>
:::
:::info
methods、computed、watch 底下的屬性,最好不要用**箭頭函式 (arrow function)**,因為**箭頭函式裡的 this** 會綁定在當前執行上下文中的this ,可能不會指向 Vue 實例而變成 undefined
:::
三次法則(rule of three):如果相同的代碼片段重複出現三次以上的時候,將其提取出來做成一個子程式就勢在必行
> https://book.vue.tw/CH1/1-3-computed-and-methods.html
> https://v3.vuejs.org/api/options-data.html#methods
>https://medium.com/unalai/%E8%AA%8D%E8%AD%98-vue-js-watch-%E7%9B%A3%E8%81%BD%E5%99%A8-ffee991368be
> https://cn.vuejs.org/v2/guide/computed.html#%E8%AE%A1%E7%AE%97%E5%B1%9E%E6%80%A7-vs-%E4%BE%A6%E5%90%AC%E5%B1%9E%E6%80%A7
###### tags: `Vue`