vue3使用watch監(jiān)聽props的值的注意事項(xiàng)及說(shuō)明
在 Vue 的響應(yīng)式系統(tǒng)中,直接監(jiān)聽 props.optionData 并啟用 deep: true 仍失效的原因,主要與 響應(yīng)式代理的復(fù)用機(jī)制 和 深度監(jiān)聽的實(shí)現(xiàn)邏輯 有關(guān)。
以下是具體分析:
一、核心原因:響應(yīng)式代理的復(fù)用
父組件傳遞新對(duì)象的代理處理
父組件通過(guò) computed 生成的 optionData 每次都是新對(duì)象,但 Vue 在子組件中接收 props.optionData 時(shí)會(huì)自動(dòng)將其轉(zhuǎn)換為 響應(yīng)式代理對(duì)象(Proxy)。
若父組件傳遞的新對(duì)象與原代理對(duì)象的 結(jié)構(gòu)相同,Vue 可能會(huì) 復(fù)用已有的代理實(shí)例,導(dǎo)致引用地址未發(fā)生明顯變化。
此時(shí),直接監(jiān)聽 props.optionData 實(shí)際監(jiān)聽的是代理對(duì)象的引用地址,而非父組件原始對(duì)象的地址。
deep: true的局限性deep: true的作用是遞歸監(jiān)聽對(duì)象 所有層級(jí)的屬性變化,但前提是 代理對(duì)象本身的引用地址已被正確追蹤 。
若代理對(duì)象的引用地址未變(被復(fù)用),即使內(nèi)部屬性發(fā)生變化,Vue 也會(huì)認(rèn)為 props.optionData 未發(fā)生“頂層”變化,從而跳過(guò)深度遍歷。
二、實(shí)驗(yàn)驗(yàn)證與現(xiàn)象解釋
- 父組件代碼示例
// 父組件每次生成新對(duì)象
const optionData = computed(() => ({
title: 'Weekly Sales',
xAxis: { data: categories.value },
series: [{ data: values.value }]
}));- 子組件監(jiān)聽邏輯
// 直接監(jiān)聽 props.optionData(失效)
watch(
props.optionData,
(newVal) => {
console.log('觸發(fā)監(jiān)聽');
},
{ deep: true } // 仍不觸發(fā)
);- 現(xiàn)象解釋
引用地址未變:Vue 復(fù)用代理對(duì)象,導(dǎo)致 props.optionData 的引用地址在子組件中未變化,因此 watch 認(rèn)為未發(fā)生“頂層”變化,跳過(guò)深度檢查。
依賴收集失敗:deep: true 需要訪問對(duì)象的所有屬性以建立依賴關(guān)系,但若代理對(duì)象未觸發(fā)屬性訪問(如未實(shí)際使用嵌套屬性),依賴鏈可能不完整。
三、解決方案
- 改用函數(shù)形式監(jiān)聽
通過(guò) 函數(shù)返回 props.optionData,強(qiáng)制 Vue 在每次依賴收集時(shí)重新獲取原始值,繞過(guò)代理復(fù)用機(jī)制:
watch(
() => props.optionData, // 動(dòng)態(tài)獲取最新值
(newVal) => {
console.log('觸發(fā)監(jiān)聽');
},
{ deep: true }
);- 強(qiáng)制生成唯一標(biāo)識(shí)
在父組件中為對(duì)象添加 唯一鍵(如時(shí)間戳),確保每次生成的新對(duì)象結(jié)構(gòu)不同,避免代理復(fù)用:
const optionData = computed(() => ({
...config,
_key: Date.now() // 破壞結(jié)構(gòu)一致性
}));- 顯式觸發(fā)引用變化
在子組件中手動(dòng)比較新舊值的 序列化結(jié)果,強(qiáng)制觸發(fā)更新:
watch(
() => JSON.stringify(props.optionData),
(newVal, oldVal) => {
if (newVal !== oldVal) {
console.log('觸發(fā)監(jiān)聽');
}
}
);總結(jié)
| 場(chǎng)景 | 直接監(jiān)聽 props.optionData | 函數(shù)形式 () => props.optionData |
|---|---|---|
| 代理復(fù)用 | 可能復(fù)用代理,引用地址未變 | 動(dòng)態(tài)獲取最新值,繞過(guò)代理復(fù)用 |
| deep: true 生效條件 | 依賴代理地址變化 | 直接追蹤原始對(duì)象變化 |
| 性能開銷 | 低(淺層監(jiān)聽) | 高(深度遞歸 + 動(dòng)態(tài)依賴收集) |
推薦方案:
- 優(yōu)先使用函數(shù)形式監(jiān)聽,并結(jié)合
deep: true確保深度屬性變化的檢測(cè)。 - 若性能敏感,可通過(guò)唯一標(biāo)識(shí)或序列化優(yōu)化依賴鏈。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Vue網(wǎng)絡(luò)請(qǐng)求的三種實(shí)現(xiàn)方式介紹
這篇文章主要介紹了Vue網(wǎng)絡(luò)請(qǐng)求的三種實(shí)現(xiàn)方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-09-09
vue項(xiàng)目開發(fā)環(huán)境工具node搭建過(guò)程
最近在開始接觸做vue框架的前端項(xiàng)目,以前用的前端比如html,js,css等都是比較原生的,寫好后直接瀏覽器打開就行,今天就先記錄一下vue的開發(fā)運(yùn)行搭建過(guò)程,感興趣的朋友一起看看吧2023-09-09
Vue觸發(fā)隱藏input file的方法實(shí)例詳解
這篇文章主要介紹了Vue觸發(fā)隱藏input file的方法實(shí)例詳解,非常不錯(cuò),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下2019-08-08
vue使用天地圖、openlayers實(shí)現(xiàn)多個(gè)底圖疊加顯示效果
這篇文章主要介紹了vue使用天地圖、openlayers實(shí)現(xiàn)多個(gè)底圖疊加顯示,根據(jù)返回的經(jīng)緯度列表通過(guò)天地圖、openlayers實(shí)現(xiàn)底圖添加,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧2022-04-04
Element?UI?table參數(shù)中的selectable的使用及遇到坑
這篇文章主要介紹了Element?UI?table參數(shù)中的selectable的使用及遇到的坑,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-08-08
vue3+element 分片上傳與分片下載功能實(shí)現(xiàn)方法詳解
這篇文章主要介紹了vue3+element 分片上傳與分片下載功能實(shí)現(xiàn)方法,結(jié)合實(shí)例形式詳細(xì)分析了vue3+element 分片上傳與下載相關(guān)實(shí)現(xiàn)技巧與操作注意事項(xiàng),需要的朋友可以參考下2023-06-06

