watch的數據源 watch函數的第一個參數是監聽的數據源,可以是: ref和computed創建的響應式數據; reactive創建的響應式對象; getter函數; 多個數據源組成的數組; 註: 響應式對象的屬性需要使用getter監聽。 當數據源是響應式對象時,其屬性的變更會觸發回調函數,但 ...
watch的數據源
watch函數的第一個參數是監聽的數據源,可以是:
- ref和computed創建的響應式數據;
- reactive創建的響應式對象;
- getter函數;
- 多個數據源組成的數組;
註:
- 響應式對象的屬性需要使用getter監聽。
- 當數據源是響應式對象時,其屬性的變更會觸發回調函數,但是接收到的
newValue
和oldValue
是一樣的,因為對象的引用是同一個。 - 和上一條不同,如果數據源是一個“返迴響應式對象”的getter,除非對象的引用變更,否則不會觸發回調函數。可以使用
deep
監聽其所有的屬性,使用遞歸實現,開銷大,謹慎使用。 - 一般watch是先設置,監聽到變化後再觸發。如果需要設置的時候就先立即觸發一次,使用
immediate
。
watchEffect
特點:
- watchEffect不需要指定依賴,只需要傳入回調函數,它會自動追蹤函數內部依賴的響應式數據,併在這些數據發生變更時觸發回調函數。
- 對於有多個依賴項的監聽器來說,不需要手動維護依賴列表,比watch方便很多。
- watchEffect預設是
immediate
的,即立即運行一個函數,同時響應式地追蹤其依賴,併在依賴更改時重新執行。 - watchEffect只在同步執行期間追蹤依賴,對於使用async await的非同步回調函數,只有在第一個await之前訪問的響應式數據會被追蹤。
偵聽器回調的觸發時機
響應式狀態的變更會同時觸發:Vue組件更新和偵聽器回調。
預設情況下,先執行偵聽器回調,再執行Vue組件更新。這意味著在偵聽器回調中的DOM是Vue更新組件之前的狀態。
可以使用flush: post
選項,調整這一順序:
watch(source, callback, {
flush: 'post'
})
watchEffect(callback, {
flush: 'post'
})
如果覺得配置選項太麻煩,對於watchEffect,有一個便捷的替代品:watchPostEffect
import { watchPostEffect } from 'vue'
watchPostEffect(() => {
/* 在 Vue 更新後執行 */
})
停止偵聽器
同步創建的偵聽器會綁定在宿主組件實例上,並會在組件卸載時自動停止。
當非同步創建了一個偵聽器時,它不會被綁定到組件上,為了防止記憶體泄漏,需要手動停止。
watch和watchEffect函數存在一個返回值,是一個用於停止偵聽器的函數:
const unwatch = watchEffect(() => {})
// ...當該偵聽器不再需要時
unwatch()
儘量不要使用非同步創建偵聽器,如果需要等待非同步數據,可以使用條件式的偵聽邏輯:
// 需要非同步請求得到的數據
const data = ref(null)
watchEffect(() => {
if (data.value) {
// 數據載入後執行某些操作...
}
})