Vue3 動(dòng)態(tài)ref問題及解決
1.問題描述
在Vue 3項(xiàng)目中,當(dāng)使用動(dòng)態(tài)ref來引用組件時(shí),刪除組件后發(fā)現(xiàn)ref對象中對應(yīng)的key仍然存在,只是值變?yōu)閌null`,而不是完全刪除該key。
在一個(gè)可拖拽的卡片列表組件中:
- 使用動(dòng)態(tài)ref來引用每個(gè)卡片中的數(shù)據(jù)列表組件
- 當(dāng)刪除卡片時(shí),需要同時(shí)清理對應(yīng)的ref引用
- 發(fā)現(xiàn)刪除后ref對象中key仍存在,值為`null`
2.示例代碼
<template> <div> <a-card v-for="item in dragList" :key="item.id"> <!-- 動(dòng)態(tài)ref的使用 --> <data-list :ref="el => { dataListRef[item.id] = el }" :doc-id="item.id" :open-type="item.openType" /> </a-card> </div> </template>
<script setup lang="ts"> import { ref } from 'vue'; const dragList = ref<any[]>([]); const dataListRef = ref<Record<string, any>>({}); // 刪除卡片方法 function remove(index: number) { const current = dragList.value[index]; // 處理編輯狀態(tài) if (current.openType === OPEN_WRITE) { const docIds = [current.id]; closeDocEntry(docIds); } // 從列表中移除 dragList.value.splice(index, 1); // 更新其他項(xiàng)目的源列表 for (let ele of dragList.value) { const oldSourceList = ele.sourceList; ele.sourceList = oldSourceList.filter((item: any) => item.sourceId !== current.id); } // Vue 會自動(dòng)處理動(dòng)態(tài) ref 的清理,無需手動(dòng)刪除,即使執(zhí)行了刪除方法,也不會刪除key // dataListRef.value[current.id] 會自動(dòng)變?yōu)?null } // 刷新所有數(shù)據(jù)列表 function reflushAllDragList() { Object.keys(dataListRef.value).forEach((key: string) => { // 過濾掉已經(jīng)被刪除的組件(值為null的情況) if (dataListRef.value[key]) { dataListRef.value[key].refresh(); } }); } </script>
說明:
①可以使用數(shù)組或者對象存儲組件的ref對象實(shí)例,因?yàn)榻M件是循環(huán)生成的,所以每個(gè)組件的ref對象需要通過這種方式進(jìn)行存儲。
② 循環(huán)生成的多個(gè)組件可以通過點(diǎn)擊刪除按鈕進(jìn)行刪除,當(dāng)組件刪除時(shí)原本想刪除ref對象中的組件對應(yīng)的ref對象,但發(fā)現(xiàn)無法刪除,最后的結(jié)果是key存在,value為null
3.原因分析
Vue 3中的動(dòng)態(tài)ref機(jī)制有以下特點(diǎn):
- 組件掛載時(shí):動(dòng)態(tài)ref會自動(dòng)將組件實(shí)例賦值給指定的key
- 組件卸載時(shí):Vue會自動(dòng)將對應(yīng)的ref值設(shè)置為`null`,但**不會刪除key**
- 響應(yīng)式處理:Vue的響應(yīng)式系統(tǒng)會在組件生命周期中自動(dòng)管理ref的狀態(tài)
為什么key不會被刪除
這是Vue 3的設(shè)計(jì)行為,不是bug:
- Vue需要保持ref對象的響應(yīng)式結(jié)構(gòu)完整性
- 避免在組件頻繁掛載/卸載時(shí)產(chǎn)生不必要的響應(yīng)式觸發(fā)
- 提供了更好的性能優(yōu)化
4.解決方案
因?yàn)闊o法刪除,所以在后續(xù)使用ref對象時(shí),需要進(jìn)行判斷是否為null,如果不為null,則執(zhí)行相關(guān)方法。
function reflushAllDragList() { Object.keys(dataListRef.value).forEach((key: string) => { // 過濾掉已經(jīng)被刪除的組件(值為null的情況) // 當(dāng)刪除card時(shí),Vue會自動(dòng)把dataListRef的對應(yīng)key的值設(shè)置為null // 不用進(jìn)行手動(dòng)刪除,即使手動(dòng)刪除,key也存在 if (dataListRef.value[key]) { dataListRef.value[key].refresh(); } }); }
5.總結(jié)
Vue 3的動(dòng)態(tài)ref在組件卸載時(shí)會自動(dòng)將值設(shè)置為`null`但保留key,這是正常的設(shè)計(jì)行為。
正確的處理方式是:
- 不要嘗試手動(dòng)刪除ref中的key
- 在使用ref時(shí)進(jìn)行null檢查
- 信任Vue的自動(dòng)管理機(jī)制
這樣可以確保代碼的穩(wěn)定性和可維護(hù)性。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Vue導(dǎo)出excel的兩個(gè)常用方式介紹與對比
這篇文章主要為大家詳細(xì)介紹了Vue導(dǎo)出excel的兩個(gè)常用方式,分別為前端vue+XLSX導(dǎo)出excel和vue+后端POI?導(dǎo)出excel,感興趣的小伙伴可以了解下2025-01-01vue實(shí)現(xiàn)動(dòng)態(tài)綁定行內(nèi)樣式style的backgroundImage
這篇文章主要介紹了vue實(shí)現(xiàn)動(dòng)態(tài)綁定行內(nèi)樣式style的backgroundImage方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07antd?Vue實(shí)現(xiàn)Login登錄頁面布局案例詳解?附帶驗(yàn)證碼驗(yàn)證功能
這篇文章主要介紹了antd?Vue實(shí)現(xiàn)Login登錄頁面布局案例詳解附帶驗(yàn)證碼驗(yàn)證功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-05-05vue中動(dòng)態(tài)參數(shù)與計(jì)算屬性的使用方法
在平時(shí)vue開發(fā)中,我們經(jīng)常會用到計(jì)算屬性(計(jì)算屬性只有在它的相關(guān)依賴發(fā)生改變時(shí)才會重新求值)來計(jì)算我們需要的數(shù)據(jù),下面這篇文章主要給大家介紹了關(guān)于vue中動(dòng)態(tài)參數(shù)與計(jì)算屬性使用的相關(guān)資料,需要的朋友可以參考下2021-08-08vue-cli 3.0 引入mint-ui報(bào)錯(cuò)問題及解決
這篇文章主要介紹了vue-cli 3.0 引入mint-ui報(bào)錯(cuò)問題及解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-05-05Vue+OpenLayers進(jìn)行項(xiàng)目開發(fā)的完整指南
在前端開發(fā)中,OpenLayers?是一個(gè)強(qiáng)大的開源地圖庫,可以用于?WebGIS?開發(fā),下面小編就來和大家詳細(xì)講講Vue使用OpenLayers進(jìn)行項(xiàng)目開發(fā)的具體步驟2025-06-06前端vue按1920*1080設(shè)計(jì)圖的頁面適配屏幕縮放并適配4K屏詳解
最近在做一個(gè)數(shù)據(jù)可視化的項(xiàng)目,整個(gè)項(xiàng)目全是大屏展示,期間也是遇到很多問題,最令人頭疼的就是大屏的適配,下面這篇文章主要給大家介紹了前端vue按1920*1080設(shè)計(jì)圖的頁面適配屏幕縮放并適配4K屏的相關(guān)資料,需要的朋友可以參考下2022-11-11vue-cli4創(chuàng)建項(xiàng)目導(dǎo)入Element-UI踩過的坑及解決
這篇文章主要介紹了vue-cli4創(chuàng)建項(xiàng)目導(dǎo)入Element-UI踩過的坑及解決,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-04-04