Vue3中我的Watch為什么總監(jiān)聽不到數(shù)據(jù)詳解
前言
vue3中, watch使用 watch(()=>xxx,v=>{})或者watch(xxx,val=>{})時(shí), 總是遇到函數(shù)寫法的watch監(jiān)聽,數(shù)據(jù)改變后沒有監(jiān)聽到數(shù)據(jù)改變;非函數(shù)的寫法反而可以監(jiān)聽到。
在 Vue 3 中,這兩種 watch 的使用方式確實(shí)有重要區(qū)別:
1. 語法區(qū)別
// 方式一:使用函數(shù)
watch(() => obj.property, (val) => {
console.log('值變化了:', val)
})
// 方式二:直接監(jiān)聽響應(yīng)式對(duì)象
watch(obj, (val) => {
console.log('對(duì)象變化了:', val)
})
2. 關(guān)鍵區(qū)別
方式一: 函數(shù)() => xxx
- 監(jiān)聽特定屬性:只追蹤
obj.property這個(gè)具體的值 - 淺層監(jiān)聽:只有當(dāng)
obj.property的值本身發(fā)生變化時(shí)才觸發(fā) - 不追蹤對(duì)象引用:不關(guān)心整個(gè)
obj對(duì)象的變化
方式二:直接監(jiān)聽響應(yīng)式對(duì)象xxx
- 監(jiān)聽整個(gè)對(duì)象:追蹤對(duì)象的所有屬性變化
- 深層監(jiān)聽:默認(rèn)深度監(jiān)聽對(duì)象內(nèi)部所有嵌套屬性的變化
- 追蹤引用變化:也會(huì)監(jiān)聽對(duì)象本身的重新賦值
3. 為什么有時(shí)候 "函數(shù)的寫法監(jiān)聽不到?"
情況一:嵌套對(duì)象屬性變化
const obj = reactive({
nested: {
value: 1
}
})
// ? 監(jiān)聽不到 nested.value 的變化
watch(() => obj.nested, (val) => {
console.log('不會(huì)觸發(fā)')
})
// ? 需要深度監(jiān)聽
watch(() => obj.nested, (val) => {
console.log('會(huì)觸發(fā)')
}, { deep: true })
// ? 或監(jiān)聽具體屬性
watch(() => obj.nested.value, (val) => {
console.log('會(huì)觸發(fā)')
})
情況二:數(shù)組操作
const arr = reactive([1, 2, 3])
// ? 監(jiān)聽不到 push/pop 等操作
watch(() => arr.length, (val) => {
console.log('可能不會(huì)觸發(fā)')
})
// ? 直接監(jiān)聽數(shù)組
watch(arr, (val) => {
console.log('會(huì)觸發(fā)')
})
情況三:解構(gòu)丟失響應(yīng)性
const obj = reactive({ x: 1, y: 2 })
// ? 解構(gòu)會(huì)丟失響應(yīng)性
const { x } = obj
watch(x, (val) => { }) // 無效
// ? 使用 getter 函數(shù)
watch(() => obj.x, (val) => {
console.log('會(huì)觸發(fā)')
})
4. 實(shí)踐建議
使用函數(shù)() => xxx的場(chǎng)景:
- 監(jiān)聽基本類型值(string, number, boolean)
- 監(jiān)聽對(duì)象的特定屬性
- 需要計(jì)算或組合的依賴
- 避免不必要的深度監(jiān)聽
// 監(jiān)聽特定屬性
watch(() => user.name, (name) => {
console.log('用戶名變化:', name)
})
// 監(jiān)聽計(jì)算值
watch(() => x.value + y.value, (sum) => {
console.log('和變化:', sum)
})
使用直接監(jiān)聽xxx的場(chǎng)景:
- 需要監(jiān)聽對(duì)象所有變化
- 監(jiān)聽數(shù)組變化
- 需要深度監(jiān)聽嵌套對(duì)象
- 監(jiān)聽引用變化
// 監(jiān)聽整個(gè)響應(yīng)式對(duì)象
watch(state, (newState) => {
console.log('狀態(tài)變化:', newState)
}, { deep: true })
// 監(jiān)聽數(shù)組
watch(items, (newItems) => {
console.log('列表變化:', newItems)
})
5. 注意事項(xiàng)
ref對(duì)象的處理:
const count = ref(0)
// ? 正確:直接監(jiān)聽 ref
watch(count, (val) => {
console.log('count變化:', val)
})
// ? 也正確:通過 .value 監(jiān)聽
watch(() => count.value, (val) => {
console.log('count變化:', val)
})
reactive對(duì)象的處理:
const state = reactive({ count: 0 })
// ? 推薦:使用 getter 監(jiān)聽特定屬性
watch(() => state.count, (val) => {
console.log('count變化:', val)
})
// ?? 注意:直接監(jiān)聽 reactive 對(duì)象會(huì)自動(dòng)開啟深度監(jiān)聽
watch(state, (val) => {
console.log('state變化:', val) // 任何嵌套屬性變化都會(huì)觸發(fā)
})
總結(jié)
選擇哪種方式主要取決于:
- 監(jiān)聽粒度:需要監(jiān)聽整個(gè)對(duì)象還是特定屬性
- 性能考慮:避免不必要的深度監(jiān)聽
- 數(shù)據(jù)類型:基本類型用 getter,復(fù)雜對(duì)象可直接監(jiān)聽
- 變化類型:需要監(jiān)聽引用變化還是值變化
當(dāng)發(fā)現(xiàn)監(jiān)聽不到變化時(shí),檢查是否是:
- 嵌套對(duì)象屬性變化(需要
deep: true) - 數(shù)組方法修改(直接監(jiān)聽數(shù)組)
- 解構(gòu)導(dǎo)致響應(yīng)性丟失(使用函數(shù))
到此這篇關(guān)于Vue3中Watch為什么總監(jiān)聽不到數(shù)據(jù)詳解的文章就介紹到這了,更多相關(guān)Vue3 Watch監(jiān)聽不到數(shù)據(jù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue 使用v-for進(jìn)行循環(huán)的實(shí)例代碼詳解
這篇文章主要介紹了vue 使用v-for進(jìn)行循環(huán)的實(shí)例代碼詳解,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-02-02
Vue 數(shù)值改變頁面沒有刷新的問題解決(數(shù)據(jù)改變視圖不更新的問題)
這篇文章主要介紹了Vue 數(shù)值改變頁面沒有刷新的問題解決(數(shù)據(jù)改變視圖不更新的問題),本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-09-09
vue.js自定義組件實(shí)現(xiàn)v-model雙向數(shù)據(jù)綁定的示例代碼
這篇文章主要介紹了vue.js自定義組件實(shí)現(xiàn)v-model雙向數(shù)據(jù)綁定的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01
vscode使用Eslint+Prettier格式化代碼的詳細(xì)操作
這篇文章主要介紹了vscode使用Eslint+Prettier格式化代碼,本文通過圖文示例代碼相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-08-08
淺析Vue中defineProps的解構(gòu)和不解構(gòu)
defineProps?是?Vue?3?Composition?API?中用來聲明組件接收的?props?的方法,本文主要為大家介紹了defineProps的解構(gòu)和不解構(gòu),感興趣的可以了解下2025-02-02
基于Vue的前端界面實(shí)現(xiàn)日期時(shí)間實(shí)時(shí)顯示簡(jiǎn)單代碼
今天在項(xiàng)目中有一個(gè)功能是要求顯示北京的實(shí)時(shí)時(shí)間,下面這篇文章主要給大家介紹了關(guān)于如何基于Vue的前端界面實(shí)現(xiàn)日期時(shí)間實(shí)時(shí)顯示的相關(guān)資料,需要的朋友可以參考下2024-01-01
Vue.js實(shí)現(xiàn)的購(gòu)物車功能詳解
這篇文章主要介紹了Vue.js實(shí)現(xiàn)的購(gòu)物車功能,結(jié)合實(shí)例形式分析了vue.js購(gòu)物車的原理、數(shù)值計(jì)算及頁面元素屬性動(dòng)態(tài)操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2019-01-01
vue實(shí)現(xiàn)給div綁定keyup的enter事件
這篇文章主要介紹了vue實(shí)現(xiàn)給div綁定keyup的enter事件,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-07-07

