目錄
1.問題描述
2.示例代碼
3.原因分析
4.解決方案
5.總結
1.問題描述
在Vue 3項目中,當使用動態ref來引用組件時,刪除組件后發現ref對象中對應的key仍然存在,只是值變為`null`,而不是完全刪除該key。
在一個可拖拽的卡片列表組件中:
* 使用動態ref來引用每個卡片中的數據列表組件
* 當刪除卡片時,需要同時清理對應的ref引用
* 發現刪除后ref對象中key仍存在,值為`null`
2.示例代碼
<template><div><a-card v-for="item in dragList" :key="item.id"><!-- 動態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];// 處理編輯狀態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 會自動處理動態 ref 的清理,無需手動刪除,即使執行了刪除方法,也不會刪除key// dataListRef.value[current.id] 會自動變為 null
}// 刷新所有數據列表
function reflushAllDragList() {Object.keys(dataListRef.value).forEach((key: string) => {// 過濾掉已經被刪除的組件(值為null的情況)if (dataListRef.value[key]) {dataListRef.value[key].refresh();}});
}
</script>
說明:
①可以使用數組或者對象存儲組件的ref對象實例,因為組件是循環生成的,所以每個組件的ref對象需要通過這種方式進行存儲。
② 循環生成的多個組件可以通過點擊刪除按鈕進行刪除,當組件刪除時原本想刪除ref對象中的組件對應的ref對象,但發現無法刪除,最后的結果是key存在,value為null
3.原因分析
Vue 3中的動態ref機制有以下特點:
- 組件掛載時:動態ref會自動將組件實例賦值給指定的key
- 組件卸載時:Vue會自動將對應的ref值設置為`null`,但**不會刪除key**
- 響應式處理:Vue的響應式系統會在組件生命周期中自動管理ref的狀態
為什么key不會被刪除
這是Vue 3的設計行為,不是bug:
* Vue需要保持ref對象的響應式結構完整性
* 避免在組件頻繁掛載/卸載時產生不必要的響應式觸發
* 提供了更好的性能優化
4.解決方案
因為無法刪除,所以在后續使用ref對象時,需要進行判斷是否為null,如果不為null,則執行相關方法。
function reflushAllDragList() {Object.keys(dataListRef.value).forEach((key: string) => {// 過濾掉已經被刪除的組件(值為null的情況)// 當刪除card時,Vue會自動把dataListRef的對應key的值設置為null// 不用進行手動刪除,即使手動刪除,key也存在if (dataListRef.value[key]) {dataListRef.value[key].refresh();}});
}
5.總結
Vue 3的動態ref在組件卸載時會自動將值設置為`null`但保留key,這是正常的設計行為。正確的處理方式是:
- 不要嘗試手動刪除ref中的key
- 在使用ref時進行null檢查
- 信任Vue的自動管理機制
這樣可以確保代碼的穩定性和可維護性。