---
# System prepended metadata

title: Vue - Methods vs Computed vs Watch
tags: [Vue]

---

# 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`