Vue3中ref數(shù)組的監(jiān)聽實(shí)現(xiàn)方式
在Vue 3中,監(jiān)聽一個由 ref 定義的數(shù)組【特別是像你這樣初始化為空數(shù)組的情況 const jjdData = ref<JJD[]>([])】,關(guān)鍵在于理解你希望監(jiān)聽何種類型的變化。
下面用一個表格匯總主要的監(jiān)聽場景和方法,方便你快速了解:
| 監(jiān)聽場景 | 推薦寫法 | 說明 |
|---|---|---|
| 數(shù)組被整體替換 | watch(jjdData, (newVal) => { ... }) | 監(jiān)聽整個數(shù)組的引用變化。 |
| 數(shù)組內(nèi)部變化(增刪元素)及元素自身變化 | watch(jjdData, (newVal) => { ... }, { deep: true }) | 最常用。深度監(jiān)聽,可響應(yīng)數(shù)組方法和元素屬性的變化。 |
| 僅監(jiān)聽數(shù)組長度的變化 | watch(() => jjdData.value.length, (newLen) => { ... }) | 只關(guān)心元素數(shù)量的增減,不關(guān)心具體內(nèi)容變化。 |
| 監(jiān)聽數(shù)組中特定對象屬性的變化 | watch(() => jjdData.value.map(item => item.someProperty), (newVals) => { ... }) | 例如,只關(guān)心每個 JJD 對象的 id 或 name 屬性是否變化。 |
監(jiān)聽器的詳細(xì)寫法與注意事項(xiàng)
1.基本監(jiān)聽與深度監(jiān)聽
對于你的 jjdData,如果它最初是空數(shù)組,然后在組件掛載后被賦值(例如通過異步請求),你需要使用深度監(jiān)聽來捕捉數(shù)組本身以及其內(nèi)部對象元素的變化。
import { watch } from 'vue';
// 深度監(jiān)聽,可以響應(yīng)數(shù)組替換、數(shù)組方法調(diào)用以及對象元素屬性的變化
watch(
jjdData,
(newArray, oldArray) => {
console.log('數(shù)組發(fā)生了變化', newArray);
// 在這里執(zhí)行你的副作用邏輯
},
{ deep: true } // 關(guān)鍵配置
);注意:
當(dāng)監(jiān)聽 reactive 定義的響應(yīng)式數(shù)據(jù)時,會強(qiáng)制開啟深度監(jiān)視,但對于 ref 定義的數(shù)組,需要顯式配置 deep: true。
使用 deep: true 時,oldArray 可能與 newArray 相同,因?yàn)樗鼈冎赶蛲粋€響應(yīng)式代理對象。
2.提取屬性進(jìn)行監(jiān)聽
如果只想監(jiān)聽數(shù)組內(nèi)對象某些特定屬性的集合變化,可以使用計(jì)算屬性提取后再監(jiān)聽,這有助于減少不必要的回調(diào)。
import { watch, computed } from 'vue';
// 提取出所有需要監(jiān)聽的屬性,組成一個新數(shù)組
const somePropertyList = computed(() => jjdData.value.map(item => item.someProperty));
watch(somePropertyList, (newValues, oldValues) => {
// 比較 newValues 和 oldValues 來確定具體哪個索引的屬性發(fā)生了變化
console.log('某個對象的someProperty發(fā)生了變化', newValues);
});
// 或者使用getter函數(shù)
watch(
() => jjdData.value.map(item => item.someProperty),
(newVals, oldVals) => { ... }
);3.動態(tài)管理監(jiān)聽器(適用于大型動態(tài)數(shù)組)
對于頻繁增刪元素的大型數(shù)組,如果需要為每個元素的特定屬性建立單獨(dú)的監(jiān)聽器,可以考慮動態(tài)管理監(jiān)聽器,但通常復(fù)雜度較高。
import { watch, onScopeDispose } from 'vue';
const stops = new Map(); // 用來存儲每個監(jiān)聽器的停止函數(shù)
// 監(jiān)聽整個數(shù)組的變化,以管理針對每個元素的監(jiān)聽器
watch(
() => [...jjdData.value],
(newArr, oldArr) => {
// 邏輯:對比新老數(shù)組,為新增元素創(chuàng)建監(jiān)聽器,為刪除的元素移除監(jiān)聽器
// ... (具體實(shí)現(xiàn)可參考搜索結(jié)果中的示例:cite[2])
},
{ deep: true }
);
// 組件卸載時清理所有監(jiān)聽器
onScopeDispose(() => {
stops.forEach(stop => stop());
stops.clear();
});除非有非常精確的需求,否則更推薦使用前面提到的深度監(jiān)聽或提取屬性監(jiān)聽的方法。
確保響應(yīng)式變化的注意事項(xiàng)
為了讓監(jiān)聽正常生效,你需要確保修改數(shù)組的方式是響應(yīng)式的:
- 變更數(shù)組本身:推薦使用數(shù)組的變更方法,如
push,pop,splice,shift,unshift等,或者直接對整個數(shù)組進(jìn)行賦值(例如jjdData.value = newArray)。 - 修改數(shù)組內(nèi)的對象元素:直接通過索引修改對象屬性(例如
jjdData.value[0].name = 'new value')在Vue 3的響應(yīng)式系統(tǒng)下是可以被deep: true檢測到的。但更推薦的做法是創(chuàng)建一個新對象進(jìn)行替換,以保證變化的可追蹤性,例如jjdData.value[0] = { ...jjdData.value[0], name: 'new value' }。
如何選擇監(jiān)聽方案
- 對于大多數(shù)情況,直接使用
deep: true進(jìn)行深度監(jiān)聽是最簡單直接的選擇。 - 如果只關(guān)心數(shù)組是否被整體替換,或者只關(guān)心數(shù)組長度的變化,可以使用非深度監(jiān)聽。
- 如果數(shù)組很大,或者只關(guān)心里面對象的某一個特定屬性,使用提取屬性并監(jiān)聽的方式性能會更優(yōu)。
- 盡量避免在大型動態(tài)數(shù)組上為每個元素單獨(dú)創(chuàng)建監(jiān)聽器,除非確有必要,因?yàn)楣芾砥饋肀容^復(fù)雜。
總結(jié)
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue項(xiàng)目中解決 IOS + H5 滑動邊界橡皮筋彈性效果(解決思路)
最近遇到一個問題,我們在企業(yè)微信中的 H5 項(xiàng)目中需要用到table表格(支持懶加載 上劃加載數(shù)據(jù)),但是他們在鎖頭、鎖列的情況下,依舊會出現(xiàn)邊界橡皮筋效果,這篇文章主要介紹了vue項(xiàng)目中解決 IOS + H5 滑動邊界橡皮筋彈性效果,需要的朋友可以參考下2023-02-02
在Vue3中實(shí)現(xiàn)四種全局狀態(tài)數(shù)據(jù)的統(tǒng)一管理的方法
在開發(fā)中,通常遇到四種全局狀態(tài)數(shù)據(jù):異步數(shù)據(jù)、同步數(shù)據(jù),傳統(tǒng)的Vue3使用不同機(jī)制處理這些數(shù)據(jù),而Zova框架通過Model機(jī)制來統(tǒng)一管理,簡化了數(shù)據(jù)處理流程,提高了代碼的可維護(hù)性,本文介紹在Vue3中實(shí)現(xiàn)四種全局狀態(tài)數(shù)據(jù)的統(tǒng)一管理的方法,感興趣的朋友一起看看吧2024-10-10
vue使用路由的query配置項(xiàng)時清除地址欄的參數(shù)案例詳解
這篇文章主要介紹了vue使用路由的query配置項(xiàng)時如何清除地址欄的參數(shù),本文通過案例給大家分享完美解決方案,需要的朋友可以參考下2023-09-09
vite打包出現(xiàn)"default"?is?not?exported?by?"no
這篇文章主要給大家介紹了關(guān)于vite打包出現(xiàn)"default"?is?not?exported?by?"node_modules/...問題解決的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-11-11
vueJS簡單的點(diǎn)擊顯示與隱藏的效果【實(shí)現(xiàn)代碼】
下面小編就為大家?guī)硪黄獀ueJS簡單的點(diǎn)擊顯示與隱藏的效果【實(shí)現(xiàn)代碼】。小編覺得挺不錯的,現(xiàn)在分享給大家,一起跟隨小編過來看看吧2016-05-05
Vue3新特性Composition?API實(shí)戰(zhàn)指南
Vue3的發(fā)布標(biāo)志著這個流行前端框架的重大升級,其中最引人注目的變化是引入了Composition?API,本文將深入探討Vue3的新特性,特別是Composition?API的實(shí)際應(yīng)用,幫助開發(fā)者掌握這一強(qiáng)大工具,需要的朋友可以參考下2025-07-07

