Vue3 動態(tài)ref問題及解決
1.問題描述
在Vue 3項目中,當(dāng)使用動態(tài)ref來引用組件時,刪除組件后發(fā)現(xiàn)ref對象中對應(yīng)的key仍然存在,只是值變?yōu)閌null`,而不是完全刪除該key。
在一個可拖拽的卡片列表組件中:
- 使用動態(tài)ref來引用每個卡片中的數(shù)據(jù)列表組件
- 當(dāng)刪除卡片時,需要同時清理對應(yīng)的ref引用
- 發(fā)現(xiàn)刪除后ref對象中key仍存在,值為`null`
2.示例代碼
<template>
<div>
<a-card v-for="item in dragList" :key="item.id">
<!-- 動態(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);
// 更新其他項目的源列表
for (let ele of dragList.value) {
const oldSourceList = ele.sourceList;
ele.sourceList = oldSourceList.filter((item: any) => item.sourceId !== current.id);
}
// Vue 會自動處理動態(tài) ref 的清理,無需手動刪除,即使執(zhí)行了刪除方法,也不會刪除key
// dataListRef.value[current.id] 會自動變?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對象實例,因為組件是循環(huán)生成的,所以每個組件的ref對象需要通過這種方式進(jìn)行存儲。
② 循環(huán)生成的多個組件可以通過點(diǎn)擊刪除按鈕進(jìn)行刪除,當(dāng)組件刪除時原本想刪除ref對象中的組件對應(yīng)的ref對象,但發(fā)現(xiàn)無法刪除,最后的結(jié)果是key存在,value為null
3.原因分析
Vue 3中的動態(tài)ref機(jī)制有以下特點(diǎn):
- 組件掛載時:動態(tài)ref會自動將組件實例賦值給指定的key
- 組件卸載時:Vue會自動將對應(yīng)的ref值設(shè)置為`null`,但**不會刪除key**
- 響應(yīng)式處理:Vue的響應(yīng)式系統(tǒng)會在組件生命周期中自動管理ref的狀態(tài)
為什么key不會被刪除
這是Vue 3的設(shè)計行為,不是bug:
- Vue需要保持ref對象的響應(yīng)式結(jié)構(gòu)完整性
- 避免在組件頻繁掛載/卸載時產(chǎn)生不必要的響應(yīng)式觸發(fā)
- 提供了更好的性能優(yōu)化
4.解決方案
因為無法刪除,所以在后續(xù)使用ref對象時,需要進(jìn)行判斷是否為null,如果不為null,則執(zhí)行相關(guān)方法。
function reflushAllDragList() {
Object.keys(dataListRef.value).forEach((key: string) => {
// 過濾掉已經(jīng)被刪除的組件(值為null的情況)
// 當(dāng)刪除card時,Vue會自動把dataListRef的對應(yīng)key的值設(shè)置為null
// 不用進(jìn)行手動刪除,即使手動刪除,key也存在
if (dataListRef.value[key]) {
dataListRef.value[key].refresh();
}
});
}5.總結(jié)
Vue 3的動態(tài)ref在組件卸載時會自動將值設(shè)置為`null`但保留key,這是正常的設(shè)計行為。
正確的處理方式是:
- 不要嘗試手動刪除ref中的key
- 在使用ref時進(jìn)行null檢查
- 信任Vue的自動管理機(jī)制
這樣可以確保代碼的穩(wěn)定性和可維護(hù)性。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
使用Vue綁定class和style樣式的幾種寫法總結(jié)
這篇文章主要介紹了使用Vue綁定class和style樣式的幾種寫法,文章通過代碼示例介紹的非常詳細(xì),具有一定的參考價值,需要的朋友可以參考下2023-07-07
vue?實現(xiàn)動態(tài)設(shè)置元素的高度
這篇文章主要介紹了在vue中實現(xiàn)動態(tài)設(shè)置元素的高度,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-08-08
Element-UI表格嵌入popover遇到的問題及解決方案
在表格中我們通常需要在每一行的一些單元格中顯示popover,這篇文章主要給大家介紹了關(guān)于Element-UI表格嵌入popover遇到的問題及解決方案,需要的朋友可以參考下2023-11-11
Vue組件狀態(tài)同步問題:修改了DOM值但提交時還是默認(rèn)值的解決方案
文章主要介紹了在使用自動化腳本操作網(wǎng)頁時遇到的常見問題,特別是在使用Vue或React等前端框架時,輸入框的值在提交表單時顯示為默認(rèn)值而不是預(yù)期值的問題,文章詳細(xì)分析了根本原因,并提供了多種解決方案,需要的朋友可以參考下2025-12-12
vue中三種插槽(默認(rèn)插槽/具名插槽/作用域插槽)的區(qū)別詳解
默認(rèn)插槽,具名插槽,作用域插槽是vue中常用的三個插槽,這篇文章主要為大家介紹了這三種插槽的使用與區(qū)別,感興趣的小伙伴可以了解一下2023-08-08
Nuxt3動態(tài)導(dǎo)入圖片(本地)src實現(xiàn)過程
這篇文章主要介紹了Nuxt3動態(tài)導(dǎo)入圖片(本地)src實現(xiàn)過程,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2026-03-03
vue如何使用el-table遍歷循環(huán)表頭和表體數(shù)據(jù)
這篇文章主要介紹了vue如何使用el-table遍歷循環(huán)表頭和表體數(shù)據(jù),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-04-04
通過vue-cli3構(gòu)建一個SSR應(yīng)用程序的方法
這篇文章主要介紹了通過vue-cli3構(gòu)建一個SSR應(yīng)用程序,以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。2018-09-09

