Vue3中ref數(shù)組的監(jiān)聽(tīng)實(shí)現(xiàn)方式
在Vue 3中,監(jiān)聽(tīng)一個(gè)由 ref 定義的數(shù)組【特別是像你這樣初始化為空數(shù)組的情況 const jjdData = ref<JJD[]>([])】,關(guān)鍵在于理解你希望監(jiān)聽(tīng)何種類(lèi)型的變化。
下面用一個(gè)表格匯總主要的監(jiān)聽(tīng)場(chǎng)景和方法,方便你快速了解:
| 監(jiān)聽(tīng)場(chǎng)景 | 推薦寫(xiě)法 | 說(shuō)明 |
|---|---|---|
| 數(shù)組被整體替換 | watch(jjdData, (newVal) => { ... }) | 監(jiān)聽(tīng)整個(gè)數(shù)組的引用變化。 |
| 數(shù)組內(nèi)部變化(增刪元素)及元素自身變化 | watch(jjdData, (newVal) => { ... }, { deep: true }) | 最常用。深度監(jiān)聽(tīng),可響應(yīng)數(shù)組方法和元素屬性的變化。 |
| 僅監(jiān)聽(tīng)數(shù)組長(zhǎng)度的變化 | watch(() => jjdData.value.length, (newLen) => { ... }) | 只關(guān)心元素?cái)?shù)量的增減,不關(guān)心具體內(nèi)容變化。 |
| 監(jiān)聽(tīng)數(shù)組中特定對(duì)象屬性的變化 | watch(() => jjdData.value.map(item => item.someProperty), (newVals) => { ... }) | 例如,只關(guān)心每個(gè) JJD 對(duì)象的 id 或 name 屬性是否變化。 |
監(jiān)聽(tīng)器的詳細(xì)寫(xiě)法與注意事項(xiàng)
1.基本監(jiān)聽(tīng)與深度監(jiān)聽(tīng)
對(duì)于你的 jjdData,如果它最初是空數(shù)組,然后在組件掛載后被賦值(例如通過(guò)異步請(qǐng)求),你需要使用深度監(jiān)聽(tīng)來(lái)捕捉數(shù)組本身以及其內(nèi)部對(duì)象元素的變化。
import { watch } from 'vue';
// 深度監(jiān)聽(tīng),可以響應(yīng)數(shù)組替換、數(shù)組方法調(diào)用以及對(duì)象元素屬性的變化
watch(
jjdData,
(newArray, oldArray) => {
console.log('數(shù)組發(fā)生了變化', newArray);
// 在這里執(zhí)行你的副作用邏輯
},
{ deep: true } // 關(guān)鍵配置
);注意:
當(dāng)監(jiān)聽(tīng) reactive 定義的響應(yīng)式數(shù)據(jù)時(shí),會(huì)強(qiáng)制開(kāi)啟深度監(jiān)視,但對(duì)于 ref 定義的數(shù)組,需要顯式配置 deep: true。
使用 deep: true 時(shí),oldArray 可能與 newArray 相同,因?yàn)樗鼈冎赶蛲粋€(gè)響應(yīng)式代理對(duì)象。
2.提取屬性進(jìn)行監(jiān)聽(tīng)
如果只想監(jiān)聽(tīng)數(shù)組內(nèi)對(duì)象某些特定屬性的集合變化,可以使用計(jì)算屬性提取后再監(jiān)聽(tīng),這有助于減少不必要的回調(diào)。
import { watch, computed } from 'vue';
// 提取出所有需要監(jiān)聽(tīng)的屬性,組成一個(gè)新數(shù)組
const somePropertyList = computed(() => jjdData.value.map(item => item.someProperty));
watch(somePropertyList, (newValues, oldValues) => {
// 比較 newValues 和 oldValues 來(lái)確定具體哪個(gè)索引的屬性發(fā)生了變化
console.log('某個(gè)對(duì)象的someProperty發(fā)生了變化', newValues);
});
// 或者使用getter函數(shù)
watch(
() => jjdData.value.map(item => item.someProperty),
(newVals, oldVals) => { ... }
);3.動(dòng)態(tài)管理監(jiān)聽(tīng)器(適用于大型動(dòng)態(tài)數(shù)組)
對(duì)于頻繁增刪元素的大型數(shù)組,如果需要為每個(gè)元素的特定屬性建立單獨(dú)的監(jiān)聽(tīng)器,可以考慮動(dòng)態(tài)管理監(jiān)聽(tīng)器,但通常復(fù)雜度較高。
import { watch, onScopeDispose } from 'vue';
const stops = new Map(); // 用來(lái)存儲(chǔ)每個(gè)監(jiān)聽(tīng)器的停止函數(shù)
// 監(jiān)聽(tīng)整個(gè)數(shù)組的變化,以管理針對(duì)每個(gè)元素的監(jiān)聽(tīng)器
watch(
() => [...jjdData.value],
(newArr, oldArr) => {
// 邏輯:對(duì)比新老數(shù)組,為新增元素創(chuàng)建監(jiān)聽(tīng)器,為刪除的元素移除監(jiān)聽(tīng)器
// ... (具體實(shí)現(xiàn)可參考搜索結(jié)果中的示例:cite[2])
},
{ deep: true }
);
// 組件卸載時(shí)清理所有監(jiān)聽(tīng)器
onScopeDispose(() => {
stops.forEach(stop => stop());
stops.clear();
});除非有非常精確的需求,否則更推薦使用前面提到的深度監(jiān)聽(tīng)或提取屬性監(jiān)聽(tīng)的方法。
確保響應(yīng)式變化的注意事項(xiàng)
為了讓監(jiān)聽(tīng)正常生效,你需要確保修改數(shù)組的方式是響應(yīng)式的:
- 變更數(shù)組本身:推薦使用數(shù)組的變更方法,如
push,pop,splice,shift,unshift等,或者直接對(duì)整個(gè)數(shù)組進(jìn)行賦值(例如jjdData.value = newArray)。 - 修改數(shù)組內(nèi)的對(duì)象元素:直接通過(guò)索引修改對(duì)象屬性(例如
jjdData.value[0].name = 'new value')在Vue 3的響應(yīng)式系統(tǒng)下是可以被deep: true檢測(cè)到的。但更推薦的做法是創(chuàng)建一個(gè)新對(duì)象進(jìn)行替換,以保證變化的可追蹤性,例如jjdData.value[0] = { ...jjdData.value[0], name: 'new value' }。
如何選擇監(jiān)聽(tīng)方案
- 對(duì)于大多數(shù)情況,直接使用
deep: true進(jìn)行深度監(jiān)聽(tīng)是最簡(jiǎn)單直接的選擇。 - 如果只關(guān)心數(shù)組是否被整體替換,或者只關(guān)心數(shù)組長(zhǎng)度的變化,可以使用非深度監(jiān)聽(tīng)。
- 如果數(shù)組很大,或者只關(guān)心里面對(duì)象的某一個(gè)特定屬性,使用提取屬性并監(jiān)聽(tīng)的方式性能會(huì)更優(yōu)。
- 盡量避免在大型動(dòng)態(tài)數(shù)組上為每個(gè)元素單獨(dú)創(chuàng)建監(jiān)聽(tīng)器,除非確有必要,因?yàn)楣芾砥饋?lái)比較復(fù)雜。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue路由事件beforeRouteLeave及組件內(nèi)定時(shí)器的清除方法
今天小編就為大家分享一篇vue路由事件beforeRouteLeave及組件內(nèi)定時(shí)器的清除方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-09-09
vue中使用 pinia 全局狀態(tài)管理的實(shí)現(xiàn)
本文主要介紹了vue中使用 pinia 全局狀態(tài)管理的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07
jenkins自動(dòng)構(gòu)建發(fā)布vue項(xiàng)目的方法步驟
這篇文章主要介紹了jenkins自動(dòng)構(gòu)建發(fā)布vue項(xiàng)目的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01
Vue實(shí)現(xiàn)一個(gè)無(wú)限加載列表功能
這篇文章主要介紹了Vue實(shí)現(xiàn)一個(gè)無(wú)限加載列表功能,需要的朋友可以參考下2018-11-11
vue3如何使用provide實(shí)現(xiàn)狀態(tài)管理詳解
Vue3中有一對(duì)新增的api,provide和inject,熟悉Vue2的朋友應(yīng)該明,這篇文章主要給大家介紹了關(guān)于vue3如何使用provide實(shí)現(xiàn)狀態(tài)管理的相關(guān)資料,需要的朋友可以參考下2021-10-10
el-date-picker日期時(shí)間選擇器的選擇時(shí)間限制到分鐘級(jí)別
文章介紹了如何使用el-date-picker 組件來(lái)限制用戶選擇的時(shí)間,禁止選擇當(dāng)前時(shí)間的日期及時(shí)分,同時(shí)允許選擇其他日期的全天時(shí)分,通過(guò)設(shè)置 `pickerOptions` 對(duì)象的屬性,可以實(shí)現(xiàn)對(duì)日期和時(shí)間的精確控制,感興趣的朋友跟隨小編一起看看吧2025-01-01
Vue在外部配置打包文件夾名稱(chēng)和url地址前綴
本文主要介紹了Vue在外部配置打包文件夾名稱(chēng)和url地址前綴,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06
Vue?Router路由hash模式與history模式詳細(xì)介紹
Vue?Router是Vue.js官方的路由管理器。它和Vue.js的核心深度集成,讓構(gòu)建單頁(yè)面應(yīng)用變得易如反掌。路由實(shí)際上就是可以理解為指向,就是我在頁(yè)面上點(diǎn)擊一個(gè)按鈕需要跳轉(zhuǎn)到對(duì)應(yīng)的頁(yè)面,這就是路由跳轉(zhuǎn)2022-08-08
antd vue 如何調(diào)整checkbox默認(rèn)樣式
這篇文章主要介紹了antd vue 如何調(diào)整checkbox默認(rèn)樣式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12

