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