文章

計算屬性與監聽器

在 Vue 3 中,計算屬性(computed properties)和 監聽器(watchers)是兩個強大且常用的工具,用來處理數據的變化。它們各自有不同的應用場景,能夠有效地提升應用的性能和可維護性。

1. 計算屬性 (Computed Properties)

計算屬性是一種基於其他響應式數據進行動態計算的屬性。當依賴的數據發生變化時,計算屬性會自動重新計算並更新結果,並且它們具有 緩存 功能,只有當相關依賴發生變化時才會重新計算。

基本使用方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<div id="app">
  <p>原始數字:</p>
  <p>雙倍數字:</p>
</div>

<script>
const app = Vue.createApp({
  data() {
    return {
      number: 5
    };
  },
  computed: {
    doubleNumber() {
      return this.number * 2;
    }
  }
});

app.mount('#app');
</script>

在這個範例中,doubleNumber 是一個計算屬性,它依賴於 number,並且會自動計算 number 的雙倍值。只要 number 改變,doubleNumber 也會相應更新。

計算屬性 vs 方法

雖然可以用方法來實現同樣的功能,但計算屬性有一個關鍵的優點——緩存。計算屬性只有在依賴的數據變化時才會重新計算,這樣可以提高性能,而方法則每次調用都會重新執行。

範例:使用方法代替計算屬性

1
2
3
4
5
6
7
8
<p>雙倍數字:</p>

<script>
methods: {
  doubleNumberMethod() {
    return this.number * 2;
  }
}

每次渲染時,doubleNumberMethod 都會重新執行,而計算屬性只在 number 改變時才會重新計算。

帶有 getter 和 setter 的計算屬性

計算屬性不僅可以有 getter,還可以有 setter,使得它們既可以讀取也可以寫入。

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
<div id="app">
  <p>雙倍數字:</p>
  <button @click="doubleNumber = 10">設定雙倍數字為 10</button>
</div>

<script>
const app = Vue.createApp({
  data() {
    return {
      number: 5
    };
  },
  computed: {
    doubleNumber: {
      get() {
        return this.number * 2;
      },
      set(newValue) {
        this.number = newValue / 2;
      }
    }
  }
});

app.mount('#app');
</script>

在這個例子中,doubleNumber 的 setter 會將數字 newValue 除以 2 並更新 number 的值。


2. 監聽器 (Watchers)

監聽器 用來監控響應式數據的變化,並在變化時執行特定的邏輯。監聽器最適合用於需要在數據變化時觸發異步操作或較重的邏輯操作。

基本使用方式

當我們需要在數據改變時執行一些邏輯,比如發送請求或處理非同步任務,監聽器會很有用。

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
<div id="app">
  <input v-model="question" placeholder="輸入問題">
  <p></p>
</div>

<script>
const app = Vue.createApp({
  data() {
    return {
      question: '',
      answer: '等待你的問題...'
    };
  },
  watch: {
    question(newQuestion, oldQuestion) {
      if (newQuestion === '') {
        this.answer = '等待你的問題...';
      } else {
        this.answer = '處理中...';
        // 模擬一個請求延遲
        setTimeout(() => {
          this.answer = '回答是:' + newQuestion;
        }, 1000);
      }
    }
  }
});

app.mount('#app');
</script>

在這個範例中,question 會被監控。當用戶輸入新問題時,監聽器會觸發,然後模擬一個延遲來更新 answer

立即執行的監聽器

有時候我們需要在實例創建時就立即執行監聽器,可以通過 immediate: true 選項來實現:

1
2
3
4
5
6
7
8
watch: {
  question: {
    handler(newQuestion) {
      // 處理邏輯
    },
    immediate: true
  }
}

深度監聽 (Deep Watch)

當要監聽一個對象內部的屬性變化時,需要啟用深度監聽。這是因為 Vue 默認只監聽對象引用的改變,而不會深入追蹤內部屬性的變化。

1
2
3
4
5
6
7
8
watch: {
  someObject: {
    handler(newValue) {
      // 處理邏輯
    },
    deep: true
  }
}

監聽多個屬性

如果要監控多個數據的變化,可以使用多個監聽器,或者直接使用一個函數來監聽這些數據:

1
2
3
4
5
6
7
8
watch: {
  question(newVal) {
    // 監聽 question 的變化
  },
  answer(newVal) {
    // 監聽 answer 的變化
  }
}

或者使用 computed 來依賴多個數據:

1
2
3
4
5
6
7
8
9
10
watch: {
  combined() {
    // 監控多個屬性的組合
  }
},
computed: {
  combined() {
    return this.question + this.answer;
  }
}

3. 選擇使用計算屬性還是監聽器?

  • 計算屬性 適合用來處理複雜的邏輯計算,並且當依賴的數據改變時才會重新計算。當需要緩存結果時,計算屬性是更好的選擇。

  • 監聽器 適合用於異步操作或需要在數據變更時進行邏輯處理的情況,尤其是需要監控一個數據的變化並觸發其他副作用的時候(如請求後端 API 或寫入本地存儲)。


總結

  • 計算屬性 是基於其他數據的屬性,它們會根據依賴數據的變化自動更新,並且具有緩存功能,適合用來進行複雜的邏輯計算。

  • 監聽器 用來監控數據的變化,當數據變化時觸發特定的行為,尤其適合處理異步操作或較重的邏輯。

這兩者能夠讓我們更靈活地處理 Vue 應用中的數據變化,提高開發效率和代碼可維護性。

本文章以 CC BY 4.0 授權