Sean's Blog

An image showing avatar

Hi, I'm Sean

這裡記錄我學習網站開發的筆記
歡迎交流 (ゝ∀・)b

LinkedInGitHub

Vue 3 Methods × Computed × Watch

本文主要內容為探討 Vue 3 的 Methods、Computed、Watch 的寫法與相關知識。

Methods vs. Computed

  • Methods:不會進行緩存,每次載入都會重新執行一次,但是可以傳入參數進行計算處理。
  • Computed:會緩存計算資料,只要原始資料沒有被更改,Computed 就不會重新執行計算。

什麼是緩存呢?

當有一份資料被修改,導致外層 DOM 重新被渲染時,如果內層資料使用的是 Computed,那麼內層資料的這個 DOM 就不用重新渲染。
但是,如果內層資料是使用 Function 得到的資料的話,Function 就會重新執行,因此就多跑了一次,效能也就會比較差。

選用方法:看需不需要傳入參數去做計算,只要不用傳參數,一律建議用 Computed 去計算資料並返回 DOM 上,才能達到緩存的效果。

範例一:用 Computed 重新包裝要呈現的字串,不會影響原本的資料內容。

1const App = {
2  const { reactive, computed } = Vue;
3  setup() {
4    // 商品列表
5    const listArr = reactive([
6      { name: "白色海豹抱枕", money: 1400 },
7      { name: "小貓咪披風", money: 600 },
8      { name: "彩色圍巾", money: 800 },
9      { name: "兔子娃娃", money: 800 },
10      { name: "白雪飄風圍巾", money: 900 }
11    ]);
12
13    // 重組字串
14    const newArr = computed(() => {
15      const mapArr = listArr.map(item => {
16        return { product: `${item.name} $: ${item.money}` };
17      });
18      console.log(mapArr);
19      return mapArr;
20    });
21
22    return {
23      newArr
24    };
25  }
26};
27

範例二:當 reactive 的資料被用 Computed 包裝起來之後,要使用這個計算結果資料時,要加上 .value 才能使用!

我們透過 console.log(newArr) 可以看到它其實是一個物件,裡面的 .value 才是我們要使用的陣列資料。

1// 商品列表展開時的高度 (每個商品 40px)
2const listHeight = computed(() => {
3  return isOpen.value ? `${newArr.value.length * 40}px` : '0px';
4});
5

資料監控 Watch

  • 有三個參數:要監控的值 (expOrFn)改變時觸發的函式{deep: true}

改變時觸發的函式

改變時觸發的函式會回傳被更改後的值 (newIndex) 與更改前的值 (oldIndex)。

1// 監控一個 ref 純值
2watch(index, (newIndex, oldIndex) => {
3  console.log('index', newIndex, oldIndex);
4});
5

要監控的值

Watch 第一個參數(要監控的值)可能包含以下幾種:

  • 使用 getter 函式 (function return),返回 ref 或 reactive 物件裡面的單一 key
  • 監控一個 ref 純值
  • 監控一個 reactive 物件整體
1// expOrFn 可以使用 JavaScript 表達式,或是一個回傳監聽目標值的函式
2watch(
3  () => refObject.value.index,
4  (newIndex, oldIndex) => {
5    console.log('refObject', newIndex, oldIndex);
6  }
7);
8
9// 這邊不是要監控 reactive 物件,而是要監控 reactive 物件裡面單一的 key,所以使用 function return 的方式
10watch(
11  () => reactiveObject.index,
12  (newIndex, oldIndex) => {
13    console.log('reactiveObject', newIndex, oldIndex);
14  }
15);
16

試著監控 ref 與 reactive 整個物件,會發現如果監控整個物件,只有 reactive 可以被成功監控到。

所以如果要監控整個物件,那麼那個物件請用 reactive 來寫,而 ref 物件還是可以監控,但是不能監控整個物件,只能監控一個 key。

1// 只有 reactive 物件可以整個被監控
2watch(refObj, (newVal) => {
3  console.log('refObj', newVal);
4});
5watch(reactiveObj, (newVal) => {
6  console.log('reactiveObj', newVal); // Proxy {idx: 1}
7});
8
9// ref 物件只能監控一個 key
10watch(
11  () => refObj.value.idx,
12  (newVal) => {
13    console.log('refObj', newVal); // refObj 1
14  }
15);
16

深層資料監控 deep

如果需要監控整個物件,但是公司又有規定要統一使用 ref 的話,那麼可以加上第三個參數 deep

1watch(
2  refObj,
3  (newVal) => {
4    console.log('data', newVal);
5  },
6  { deep: true }
7);
8

但是 deep 是針對每一個 key 做掃描,所以效能耗費大,盡量還是少用,只有真的需要大範圍掃描時才使用。

回顧

看完這篇文章,我們到底有什麼收穫呢?藉由本文可以理解到…

  • Vue 3 Methods 與 Computed 的使用時機與差異
  • Vue 3 使用 Watch 監控資料的方式

以上資源是我自己整理過後的筆記,若有錯誤歡迎隨時和我聯繫