iT邦幫忙

2025 iThome 鐵人賽

DAY 9
0
Vue.js

邊學邊做:Vue.js 實戰養成計畫系列 第 9

Day 9:計算的軌道 — computed 與 watch

  • 分享至 

  • xImage
  •  

隨著專案功能越來越複雜,若在模板裡塞進一堆運算式,畫面會變得雜亂難懂,也不好維護。Vue 提供了 computedwatch,一個幫你「自動算值」,一個幫你「盯資料」。

1)Computed(計算屬性)是什麼?

將邏輯運算抽離到 computed 屬性,讓模板更乾淨。

重點:

  • 會快取結果(只要依賴的資料沒變,就不會重算)。
  • 適合用來處理「從現有資料推導新值」的情境。

比喻:
想像你有星球的半徑和公轉時間,computed 就像一台「宇宙計算機」,自動算出公轉速度。

範例改寫(before → after)

未使用 computed(模板很亂):

<template>
  <p>這顆星球是否有衛星?</p>
  <span>{{ planet.moons.length > 0 ? '有' : '沒有' }}</span>
</template>

使用 computed(模板更乾淨):

<script setup>
import { reactive, computed } from 'vue'

const planet = reactive({
  name: '火星',
  moons: ['Phobos', 'Deimos']
})

const hasMoons = computed(() => {
  return planet.moons.length > 0 ? '有' : '沒有'
})
</script>

<template>
  <p>這顆星球是否有衛星?</p>
  <span>{{ hasMoons }}</span>
</template>

2)Watch(監聽器)是什麼?

一個專門「盯資料」的小幫手,資料一變,就立刻做事。

重點:

  • 用來觸發 副作用(side effect),像是 API 請求、寫 log、觸發動畫。
  • 預設只會在資料變動時觸發,可以透過選項改變行為。

比喻:

  • 就像天文台盯著火星,如果發現軌道偏移,就馬上拉警報。

基本語法:放在 <script setup> 區塊裡,因為它是 JavaScript 程式碼,用來寫邏輯的。

watch(
  source,       // 要監聽的資料
  (newVal, oldVal) => { 
    // 這裡寫當資料變化後要做的事
  },
  { options }   // 可選:deep, immediate, once, flush...
)

Watch 進階選項

  • deep: true → 監聽物件內部所有屬性(但大資料會很耗效能)。

  • immediate: true → 初始化時就執行一次 callback。

  • once: true → 只執行一次就結束監聽。

watchEffect

  • 更簡潔的寫法,不用指定監聽對象,會自動追蹤函式中用到的所有響應式資料。
  • 一開始就會執行一次,不需要加 immediate
watchEffect(() => {
  console.log(`星球數量:${planets.value.length}`)
})

3)範例:行星探索中心

<template>
  <div>
    <h2>🪐 行星探索中心</h2>

    <label>輸入找到的星球數:</label>
    <input type="number" v-model="planetCount" />

    <p>✨ 星球總數:{{ planetCount }}</p>
    <p>🌌 任務等級 (computed):{{ missionLevel }}</p>
    <p>📡 最新通知 (watch):{{ notice }}</p>
  </div>
</template>

<script setup>
import { ref, computed, watch } from 'vue'

const planetCount = ref(0)

// computed:根據星球數量自動判斷任務等級
const missionLevel = computed(() => {
  if (planetCount.value < 0) return '錯誤任務'
  if (planetCount.value < 3) return 'C級任務'
  if (planetCount.value < 7) return 'B級任務'
  if (planetCount.value < 10) return 'A級任務'
  return 'S級星際探險家'
})

// watch:盯著星球數,一旦變化就回報
const notice = ref('')
watch(planetCount, (newVal, oldVal) => {
  if (newVal > oldVal) {
    notice.value = `🌠 發現新星球!總數變成 ${newVal} 顆`
  } else {
    notice.value = `⚠️ 星球數量變動 (從 ${oldVal} → ${newVal})`
  }
  if (newVal < 0 ) {
    notice.value = `🌠 探索錯誤!總數變成 ${newVal} 顆`
  }
})
</script>

https://ithelp.ithome.com.tw/upload/images/20250917/20178644W242dHnnUl.png
結果:

  • 輸入數字 → 會即時更新「星球總數」。
  • computed → missionLevel 自動計算任務等級。
  • watch → notice 會馬上回報星球數量的變化。

今天我們體驗了 computed 與 watch 的強大威力,學會自動推導與監控資料。
明天我們將轉向「畫面表現」:
如何用 :class 和 :style 動態改變樣式?
如何讓條件改變時,自動切換 CSS?
一起在 CSS星塵裡,我們會用 Vue 的樣式綁定技巧,讓星球在條件改變時自動閃爍、變色,帶點魔法般的感覺。

參考資源
https://vuejs.org/guide
https://www.runoob.com/vue3


上一篇
Day 8:事件流星雨 — v-on 與事件處理
下一篇
Day 10:CSS 星塵 — Vue 中的樣式與 class 綁定
系列文
邊學邊做:Vue.js 實戰養成計畫10
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言