理解 vue3 的 watch 函數
計算屬性允許我們聲明性地計算衍生值。然而在有些情況下,我們需要在狀態變化時執行一些 “副作用”:例如更改 DOM,或是根據異步操作的結果去修改另一處的狀態。
在組合式 API 中,我們可以使用 watch 函數在每次響應式狀態發生變化時觸發回調函數。
偵聽數據源類型
watch 的第一個參數可以是不同形式的 “數據源”:它可以是一個 ref (包括計算屬性)、一個響應式對象、一個 getter 函數、或多個數據源組成的數組:
const x = ref(0)
const y = ref(0)
// 單個 ref
watch(x, (newX) => {
console.log(`x is ${newX}`)
})
// getter 函數
watch(
() => x.value + y.value,
(sum) => {
console.log(`sum of x + y is: ${sum}`)
}
)
// 多個來源組成的數組
watch([x, () => y.value], ([newX, newY]) => {
console.log(`x is ${newX} and y is ${newY}`)
})
注意,你不能直接偵聽響應式對象的屬性值,例如:
const obj = reactive({ count: 0 })
// 錯誤,因爲 watch() 得到的參數是一個 number
watch(obj.count, (count) => {
console.log(`count is: ${count}`)
})
這裏需要用一個返回該屬性的 getter 函數:
// 提供一個 getter 函數
watch(
() => obj.count,
(count) => {
console.log(`count is: ${count}`)
}
)
深層偵聽器
直接給 watch() 傳入一個響應式對象,會隱式地創建一個深層偵聽器——該回調函數在所有嵌套的變更時都會被觸發:
const obj = reactive({ count: 0 })
watch(obj, (newValue, oldValue) => {
// 在嵌套的屬性變更時觸發
// 注意:`newValue` 此處和 `oldValue` 是相等的
// 因爲它們是同一個對象!
})
obj.count++
相比之下,一個返回響應式對象的 getter 函數,只有在返回不同的對象時,纔會觸發回調:
watch(
() => state.someObject,
() => {
// 僅當 state.someObject 被替換時觸發
}
)
你也可以給上面這個例子顯式地加上 deep 選項,強制轉成深層偵聽器:
watch(
() => state.someObject,
(newValue, oldValue) => {
// 注意:`newValue` 此處和 `oldValue` 是相等的
// *除非* state.someObject 被整個替換了
},
{ deep: true }
)
謹慎使用
深度偵聽需要遍歷被偵聽對象中的所有嵌套的屬性,當用於大型數據結構時,開銷很大。因此請只在必要時才使用它,並且要留意性能。
總結
watch() 默認是懶偵聽的,即僅在偵聽源發生變化時才執行回調函數。
第一個參數是偵聽器的源。這個來源可以是以下幾種:
- 一個函數,返回一個值 2. 一個 ref3. 一個響應式對象 4.... 或是由以上類型的值組成的數組
第二個參數是在發生變化時要調用的回調函數。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/pFDOTzlvyCGN0ZHTcJa4Jg