Vue中深克隆的3種實現(xiàn)方案
深克?。ㄉ羁截悾┑暮诵氖?strong>復制一個對象/數(shù)組,且拷貝后的對象與原對象完全獨立,修改拷貝對象不會影響原對象(包括嵌套層級的屬性/元素)。在Vue開發(fā)中,深克隆常用于處理響應式數(shù)據(jù)(如ref、reactive創(chuàng)建的數(shù)據(jù)),避免因淺拷貝導致的響應式異常,以下是3種實用實現(xiàn)方案,從簡單到完善,覆蓋不同場景。
一、核心前提:淺克隆 vs 深克?。ū囟畢^(qū)別)
先明確淺克隆與深克隆的差異,避免混淆:
- 淺克隆:僅復制對象的第一層屬性,嵌套的對象/數(shù)組仍指向原引用(修改嵌套內(nèi)容會影響原對象),如Object.assign()、擴展運算符(...)。
- 深克隆:復制對象的所有層級(包括嵌套的對象、數(shù)組、函數(shù)等),拷貝后與原對象完全脫離引用,互不影響(這是Vue開發(fā)中常用的方式)。
Vue中注意點:對于reactive創(chuàng)建的響應式對象,直接克隆會丟失響應式特性,需特殊處理;ref對象需先獲取.value再克隆。
二、方案1:基礎版深克?。ㄟm配普通對象/數(shù)組,無復雜類型)
適用于:普通對象、數(shù)組,無函數(shù)、Date、RegExp等復雜類型,代碼簡潔,上手快。
核心邏輯:利用JSON.stringify()將對象轉(zhuǎn)為字符串,再用JSON.parse()轉(zhuǎn)回對象,實現(xiàn)深度拷貝(本質(zhì)是序列化+反序列化)。
// 基礎版深克?。╒ue中可直接使用,適配簡單數(shù)據(jù))
function deepCloneBasic(obj) {
// 處理null和非對象/數(shù)組類型(直接返回,無需克?。?
if (obj === null || typeof obj !== 'object') {
return obj;
}
// 利用JSON序列化+反序列化實現(xiàn)深克隆
return JSON.parse(JSON.stringify(obj));
}
// Vue中測試示例(普通數(shù)據(jù))
const obj = { name: 'Vue', info: { version: '3.4.21' }, list: [1, 2, 3] };
const cloneObj = deepCloneBasic(obj);
// 修改拷貝對象,原對象不受影響
cloneObj.info.version = '3.5.0';
cloneObj.list.push(4);
console.log(obj.info.version); // 3.4.21(原對象不變)
console.log(obj.list); // [1,2,3](原對象不變)
優(yōu)點:代碼簡潔,無需復雜邏輯,適配大部分簡單場景;
缺點:無法克隆函數(shù)、Date、RegExp、undefined、Symbol等復雜類型(會丟失或變形),不適合包含這些類型的數(shù)據(jù)。
三、方案2:完善版深克?。ㄟm配所有類型,通用推薦)
適用于:所有數(shù)據(jù)類型(對象、數(shù)組、函數(shù)、Date、RegExp等),解決基礎版的缺陷,是Vue開發(fā)中最常用的通用方案。
核心邏輯:遞歸遍歷對象/數(shù)組,對不同類型的數(shù)據(jù)分別處理,確保所有層級都被深度拷貝,不丟失類型和屬性。
// 完善版深克隆(適配所有類型,Vue通用)
function deepClonePerfect(obj) {
// 1. 處理null和非對象類型(直接返回)
if (obj === null || typeof obj !== 'object') {
return obj;
}
// 2. 處理Date類型(避免Date被轉(zhuǎn)為普通對象)
if (obj instanceof Date) {
return new Date(obj);
}
// 3. 處理RegExp類型(保留正則的修飾符)
if (obj instanceof RegExp) {
return new RegExp(obj.source, obj.flags);
}
// 4. 處理數(shù)組和對象(區(qū)分數(shù)組和普通對象)
// 創(chuàng)建一個與原對象類型一致的空容器(數(shù)組→數(shù)組,對象→對象)
const cloneObj = Array.isArray(obj) ? [] : {};
// 5. 遞歸遍歷所有屬性,深度拷貝
for (let key in obj) {
// 只拷貝對象自身的屬性(排除原型鏈上的屬性)
if (obj.hasOwnProperty(key)) {
// 遞歸克隆子屬性(嵌套對象/數(shù)組)
cloneObj[key] = deepClonePerfect(obj[key]);
}
}
return cloneObj;
}
// Vue中測試示例(復雜數(shù)據(jù))
const complexObj = {
name: '深克隆',
date: new Date(),
reg: /vue/g,
func: () => console.log('vue'),
info: { a: 1, b: { c: 2 } },
list: [1, [2, 3]]
};
const cloneComplex = deepClonePerfect(complexObj);
cloneComplex.info.b.c = 100;
cloneComplex.list[1].push(4);
cloneComplex.date.setFullYear(2025);
console.log(complexObj.info.b.c); // 2(原對象不變)
console.log(complexObj.list[1]); // [2,3](原對象不變)
console.log(complexObj.date.getFullYear()); // 2024(原對象不變)
console.log(cloneComplex.func()); // vue(函數(shù)正常克?。?
優(yōu)點:適配所有數(shù)據(jù)類型,克隆徹底,無數(shù)據(jù)丟失,滿足Vue中復雜數(shù)據(jù)的克隆需求;
缺點:代碼稍復雜,無需額外依賴,可直接封裝到Vue項目中復用。
四、方案3:Vue專屬深克?。ㄟm配響應式數(shù)據(jù),推薦)
適用于:Vue2/Vue3的響應式數(shù)據(jù)(ref、reactive創(chuàng)建的數(shù)據(jù)),解決“克隆后丟失響應式”的問題,結(jié)合Vue內(nèi)置API,更貼合Vue開發(fā)場景。
核心邏輯:利用Vue內(nèi)置的reactive、ref API,克隆后重新創(chuàng)建響應式對象,確??寺『蟮臄?shù)據(jù)仍保持響應式特性。
1. Vue3 專屬實現(xiàn)(適配ref、reactive)
<script setup>
import { ref, reactive, isRef, isReactive, toRaw } from 'vue'
// Vue3專屬深克?。ūA繇憫剑?
function deepCloneVue3(obj) {
// 處理ref對象:先獲取原始值,克隆后重新創(chuàng)建ref
if (isRef(obj)) {
const rawValue = toRaw(obj.value); // 轉(zhuǎn)為原始值(避免響應式干擾)
const cloneValue = deepClonePerfect(rawValue); // 用完善版克隆原始值
return ref(cloneValue); // 重新創(chuàng)建ref,保留響應式
}
// 處理reactive對象:先獲取原始值,克隆后重新創(chuàng)建reactive
if (isReactive(obj)) {
const rawObj = toRaw(obj); // 轉(zhuǎn)為原始對象
const cloneObj = deepClonePerfect(rawObj); // 深度克隆
return reactive(cloneObj); // 重新創(chuàng)建reactive,保留響應式
}
// 非響應式數(shù)據(jù),直接用完善版克隆
return deepClonePerfect(obj);
}
// 測試示例
const reactiveObj = reactive({ name: 'Vue3', info: { age: 5 } });
const refObj = ref({ a: 1, b: [2, 3] });
// 克隆響應式數(shù)據(jù)
const cloneReactive = deepCloneVue3(reactiveObj);
const cloneRef = deepCloneVue3(refObj);
// 修改克隆對象,原對象不受影響,且克隆對象仍有響應式
cloneReactive.info.age = 10;
cloneRef.value.b.push(4);
console.log(reactiveObj.info.age); // 5(原對象不變)
console.log(refObj.value.b); // [2,3](原對象不變)
console.log(cloneReactive.info.age); // 10(克隆對象響應式正常)
</script>
2. Vue2 專屬實現(xiàn)(適配data、ref、reactive)
// Vue2專屬深克隆(保留響應式,需引入Vue)
import Vue from 'vue'
function deepCloneVue2(obj) {
// 處理Vue2的響應式對象(data中定義的對象、Vue.observable創(chuàng)建的對象)
if (Vue.isReactive(obj) || Vue.isVue(obj)) {
// 用Vue.extend創(chuàng)建臨時組件,通過props傳遞數(shù)據(jù),實現(xiàn)響應式克隆
const TempComponent = Vue.extend({
props: Object.keys(obj),
render: function() {}
});
const instance = new TempComponent({ propsData: obj });
return instance._props;
}
// 處理ref對象(Vue2的ref需通過.value訪問)
if (obj && obj._isRef) {
const cloneValue = deepClonePerfect(obj.value);
return Vue.ref(cloneValue);
}
// 非響應式數(shù)據(jù),用完善版克隆
return deepClonePerfect(obj);
}
// 測試示例(Vue2)
const vue2Reactive = Vue.observable({ name: 'Vue2', list: [1, 2] });
const cloneVue2 = deepCloneVue2(vue2Reactive);
cloneVue2.list.push(3);
console.log(vue2Reactive.list); // [1,2](原對象不變)
console.log(cloneVue2.list); // [1,2,3](克隆對象響應式正常)
優(yōu)點:專門適配Vue響應式數(shù)據(jù),克隆后不丟失響應式特性,貼合Vue開發(fā)場景;
缺點:依賴Vue內(nèi)置API,需區(qū)分Vue2和Vue3版本。
五、Vue中深克隆的注意事項
- 克隆響應式數(shù)據(jù)時,不可直接用基礎版(JSON方式),會丟失響應式特性,需用Vue專屬方案;
- Vue3中,reactive對象克隆前需用toRaw()轉(zhuǎn)為原始對象,否則會因響應式代理導致克隆異常;
- 避免克隆Vue組件實例、Vuex狀態(tài)等特殊對象,這類對象克隆后可能無法正常使用;
- 若項目中頻繁使用深克隆,可將完善版/Vue專屬版封裝為全局工具函數(shù)(如utils/clone.js),方便復用;
- 簡單場景(無復雜類型、非響應式數(shù)據(jù))可直接用基礎版,復雜場景優(yōu)先用完善版,響應式數(shù)據(jù)用Vue專屬版。
六、總結(jié)(方案選擇建議)
- 簡單場景(普通對象/數(shù)組,無復雜類型):方案1(基礎版),簡潔高效;
- 通用場景(所有數(shù)據(jù)類型,非響應式):方案2(完善版),克隆徹底,無數(shù)據(jù)丟失;
- Vue開發(fā)場景(響應式數(shù)據(jù)):方案3(Vue專屬版),保留響應式,貼合Vue特性。
實際開發(fā)中,可根據(jù)數(shù)據(jù)類型和是否為響應式,選擇對應的方案,建議將方案2和方案3封裝為全局工具,提升開發(fā)效率。
以上就是Vue中深克隆的3種實現(xiàn)方案的詳細內(nèi)容,更多關于Vue深克隆實現(xiàn)方案的資料請關注腳本之家其它相關文章!
相關文章
SpringBoot實現(xiàn)全局和局部跨域的兩種方式
本文主要介紹了SpringBoot實現(xiàn)全局和局部跨域的兩種方式,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-01-01
Vue利用vue-baidu-map實現(xiàn)獲取經(jīng)緯度和搜索地址
在開發(fā)項目的時候,發(fā)現(xiàn)需要獲取經(jīng)緯度,由于這個項目是用vue寫的,最后決定使用vue-baidu-map來快速獲取經(jīng)緯度,感興趣的可以了解一下2022-09-09
Vue中使用v-print打印出現(xiàn)空白頁問題及解決
這篇文章主要介紹了Vue中使用v-print打印出現(xiàn)空白頁問題及解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-09-09
vue-cli創(chuàng)建項目及項目結(jié)構(gòu)解析
上一篇我們安裝了vue-cli,接下來我們就使用該腳手架進行創(chuàng)建項目,這篇文章主要介紹了vue-cli創(chuàng)建項目以及項目結(jié)構(gòu)的相關資料,需要的朋友可以參考下面文章的具體內(nèi)容2021-10-10

