watch
與 watchEffect
的差異
功能 / 特性 |
watch |
watchEffect |
參數 |
(newValue, oldValue) |
() |
查詢舊值 |
可以 |
不能 |
觸發條件 |
屬性改變時觸發 (可設定 immediate 可使初始化時觸發一次) |
初始化時觸發一次,隨後屬性改變時再觸發 |
屬性指定 |
需要指定監聽的屬性 |
不需要指定具體屬性 |
停止監聽 |
無法停止 |
可以主動停止監聽 |
多次觸發執行 |
是 |
是(可進行節流) |
使用方式
基本用法
watch
在初始化時不會立即執行,必須等到監聽的值發生變化後才會觸發回調函數。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <script setup> import { ref, watch, watchEffect } from 'vue'
const text = ref('你好')
watchEffect(() => { console.log('watchEffect:', text.value) })
watch(text, (newValue, oldValue) => { console.log('watch text:', `新值: ${newValue}`, `舊值: ${oldValue}`) })
watch(() => text.value, (newValue, oldValue) => { console.log('watch text.value:', `新值: ${newValue}`, `舊值: ${oldValue}`) })
setTimeout(() => { text.value = 'Hello' }, 2000) </script>
|

當設定 immediate: true
時,watch
會在初始化時立即執行一次回調函數,並持續監聽該屬性的變化。
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 31
| <script setup> import { ref, watch, watchEffect } from 'vue'
const text = ref('你好')
watchEffect(() => { console.log('watchEffect:', text.value) })
watch( text, (newValue, oldValue) => { console.log('watch1:', newValue, oldValue) }, { immediate: true } )
watch( () => text.value, (newValue, oldValue) => { console.log('watch2:', newValue, oldValue) }, { immediate: true } )
setTimeout(() => { text.value = 'Hello' }, 2000) </script>
|

停止監聽 watchEffect
watchEffect
返回一個停止監聽的函數,你可以在需要時調用它來停止監聽。
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
| <script setup> import { ref, watch, watchEffect } from 'vue'
const count = ref(0) const stop = watchEffect(() => { console.log(`watchEffect: ${count.value}`) })
const changeCount = () => { count.value += 1
if (count.value > 5) stop() }
watch(count, (newValue, oldValue) => { console.log(`newValue: ${newValue}, oldValue: ${oldValue}`) }) </script>
<template> <div class="text-right"> <button type="button" @click="changeCount"> 改變-count: {{ count }} </button> </div> </template>
|
當 count
的值大於 5 時,watchEffect
會停止監聽。

物件監聽的用法
如果監聽的對象不是 Proxy 物件,必須使用 () => 屬性
的語法,否則會出現以下警告:
1
| [Vue warn]: Invalid watch source: A watch source can only be a getter/effect function, a ref, a reactive object, or an array of these types.
|
以下範例展示了如何正確監聽整個物件或單一屬性。
整筆資料進行監聽
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 31 32 33 34 35 36
| <script setup> import { ref, reactive, watch } from 'vue';
const product = ref({ name: '麥香奶茶', price: 10, num: 24, })
watch(product.value, (n) => { console.log('product:', n); });
const user = reactive({ name: 'Mike', age: 12, email: '[email protected]', })
watch(user, (n) => { console.log('user:', n); });
setTimeout(() => { user.email = '[email protected]'; product.value.num += 24 }, 2000); </script>
<template> <div> {{ user.email }} <hr> {{ product.num }} </div> </template>
|

單一資料進行監聽
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 31 32 33 34 35 36
| <script setup> import { ref, reactive, watch } from 'vue';
const product = ref({ name: '麥香奶茶', price: 10, num: 24, })
watch(() => product.value.num, (n) => { console.log('product:', n); });
const user = reactive({ name: 'Mike', age: 12, email: '[email protected]', })
watch(() => user.email, (n) => { console.log('user:', n); });
setTimeout(() => { user.email = '[email protected]'; product.value.num += 24 }, 2000); </script>
<template> <div> {{ user.email }} <hr> {{ product.num }} </div> </template>
|

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 31 32 33 34 35 36
| <script setup> import { ref, reactive, watch } from 'vue';
const product = ref({ name: '麥香奶茶', price: 10, num: 24, })
watch(product.value.num, (n) => { console.log('product:', n); });
const user = reactive({ name: 'Mike', age: 12, email: '[email protected]', })
watch(user.email, (n) => { console.log('user:', n); });
setTimeout(() => { user.email = '[email protected]'; product.value.num += 24 }, 2000); </script>
<template> <div> {{ user.email }} <hr> {{ product.num }} </div> </template>
|

總結
watch
主要用於監聽特定資料的變化,並允許在回調中訪問舊值。使用時需要明確指定要監聽的屬性,並且可以選擇是否在初始化時立即執行一次回調。這使得 watch
非常適合用來處理具體資料變動的場景,尤其是當你需要在資料變化時執行某些操作或獲取舊值時。
watchEffect
則是用來自動追蹤並處理資料變化後的後續自動識別在回調中使用到的所有響應式資料,操作。它會並且不需要你明確指定要監聽的屬性。這使得 watchEffect
特別適用於需要處理多個資料變化並且不確定具體哪些資料會變動的情境。watchEffect
也可以返回一個停止監聽的函數,允許手動控制監聽的結束。
總體來說,watch
和 watchEffect
各有不同的使用場景。當需要精確控制監聽某一屬性並且希望訪問舊值時,watch
是理想選擇;而當需要自動追蹤多個資料變化並執行後續操作時,watchEffect
更為便捷。選擇何者取決於你的具體需求,兩者在 Vue 中各自扮演著不同但互補的角色。