国产成人精品久久免费动漫-国产成人精品天堂-国产成人精品区在线观看-国产成人精品日本-a级毛片无码免费真人-a级毛片毛片免费观看久潮喷

您的位置:首頁技術文章
文章詳情頁

Vue父子組件傳值的一些坑

瀏覽:4日期:2022-11-21 18:47:57

在用 Vue 的父子組件傳值時遇到一個冷門的問題,子組件改變值后父組件的值也隨之改變了,特此記錄下原因和解決方式。再系統梳理下 JavaScript 的深拷貝與淺拷貝相關知識點。

1. 問題描述

父組件傳值給子組件,子組件改變傳過來的值后,父組件的值也會跟著改變。這個問題比較冷門,平時如果對組件通信使用得比較簡單,一般不會遇到。

2. 原因剖析

核心:雙向綁定

父子組件傳值的時候涉及雙向綁定,當傳值為 object 類型時,傳值之后數據源會被改變。

深拷貝與淺拷貝

下文詳細講。

3. 解決方案

我目前采用的解決辦法是:傳值的時候不要直接傳數據源,而是通過拷貝或者定義新變量等方式傳值。

簡單處理就 JSON.parse(JSON.stringify(obj)),但是這種簡單粗暴的方法有其局限性。當值為 undefined、function、symbol 會在轉換過程中被忽略。所以,對象值有這三種的話用這種方法會導致屬性丟失。

剩下的就是自寫深拷貝的工具函數,或者直接借助第三方的庫函數,下面展開講。

4. 深拷貝和淺拷貝

JavaScript中的淺拷貝與深拷貝,只是針對復雜數據類型(Object,Array)的復制問題。淺拷貝與深拷貝都可以實現在已有對象上再生出一份的作用。但是對象的實例是存儲在堆內存中然后通過一個引用值去操作對象,由此拷貝的時候就存在兩種情況了:拷貝引用和拷貝實例,這也是淺拷貝和深拷貝的區別。

下圖為JavaScript復雜數據類型的淺拷貝示意圖:

Vue父子組件傳值的一些坑

淺拷貝

淺拷貝是拷貝引用,拷貝后的引用都是指向同一個對象的實例,彼此之間的操作會互相影響。

值得注意的是:Object.assgin() 是淺拷貝,它只能深拷貝第一層,深層的還是淺拷貝。因為 Object.assign() 拷貝的是屬性值。假如源對象的屬性值是一個對象的引用,那么它也只指向那個引用。(摘選自MDN)

MDN講述 assign 的時候,就有一個典型的例子,這里是文章鏈接。

下面列舉第一類淺拷貝 - 拷貝原對象的引用:

/** * 對象的淺拷貝 */var obj1 = { name:’wenyuan’, age: 22}var obj2 = obj1;obj2[’job’] = ’coder’;console.log(obj1); //Object {name: 'wenyuan', age: 22, job: 'coder'}console.log(obj2); //Object {name: 'wenyuan', age: 0, job: 'coder'}/* ------------------------- 華麗的分割線 ------------------------- *//** * 數組的淺拷貝 */var arr1 = [1, 2, 3, ’4’];var arr2 = arr1;arr2[1] = 'test'; console.log(arr1); // [1, 'test', 3, '4']console.log(arr2); // [1, 'test', 3, '4']

接下來看第二類淺拷貝 - 源對象拷貝實例,其屬性對象拷貝引用:

這種情況,外層源對象是拷貝實例,如果其屬性元素為復雜數據類型(Object、Array)時,內層元素拷貝引用。

對源對象直接操作,不影響另外一個對象,但是對其屬性操作時候,會改變另外一個對象的屬性的值。

/** * 對象的淺拷貝 * jQuery的 $.extend(a,b) 或 $.extend({},a,b) */var obj1 = { name:’wenyuan’, age: 22, social: { blog: ’www.wenyuanblog.com’ }, skills: [’js’, ’html’, ’css’, ’python’]}var obj2 = $.extend({},obj1);console.log(obj1 === obj2) // 輸出false,說明外層數組拷貝的是實例console.log(obj1.social === obj2.social) // 輸出true,說明對于Object類型的屬性是拷貝引用console.log(obj1.skills === obj2.skills) // 輸出true,說明對于Array類型的屬性是拷貝引用/** * 對象的淺拷貝 * ES6的 Object.assign() 和 對象擴展運算符... */var obj1 = { name:’wenyuan’, age: 22, social: { blog: ’www.wenyuanblog.com’ }, skills: [’js’, ’html’, ’css’, ’python’]}var obj2 = Object.assign({},obj1);console.log(obj1 === obj2) // 輸出false,說明外層數組拷貝的是實例console.log(obj1.social === obj2.social) // 輸出true,說明對于Object類型的屬性是拷貝引用console.log(obj1.skills === obj2.skills) // 輸出true,說明對于Array類型的屬性是拷貝引用var obj3 = {...obj1};console.log(obj1 === obj3) // 輸出false,說明外層數組拷貝的是實例console.log(obj1.skills === obj3.skills) // 輸出true,說明對于Array類型的屬性是拷貝引用console.log(obj1.skills === obj3.skills) // 輸出true,說明對于Array類型的屬性是拷貝引用/* ------------------------- 華麗的分割線 ------------------------- *//** * 數組的淺拷貝 * Array.prototype.slice() */var arr1 = [{name: 'wenyuan'}, {name: 'Evan You'}];var arr2 = arr1.slice(0);console.log(arr1 === arr2); // 輸出false,說明外層數組拷貝的是實例console.log(arr1[0] === arr2[0]); // 輸出true,說明其元素拷貝的是引用/** * 數組的淺拷貝 * Array.prototype.concat() */var arr1 = [{name: 'wenyuan'}, {name: 'Evan You'}];var arr2 = arr1.concat();console.log(arr1 === arr2); // 輸出false,說明外層數組拷貝的是實例console.log(arr1[0] === arr2[0]); // 輸出true,說明其元素拷貝的是引用/** * 數組的淺拷貝 * ES6的 Object.assign() 和 對象擴展運算符... * 由于數組是特殊的對象,所以ES6中的這種方式也可以用于數組 */var arr1 = [{name: 'wenyuan'}, {name: 'Evan You'}];var arr2 = Object.assign([],arr1)var arr3 = { ...arr1 };console.log(arr1 === arr2); // 輸出false,說明外層數組拷貝的是實例console.log(arr1 === arr3); // 輸出false,說明外層數組拷貝的是實例console.log(arr1[0] === arr2[0]); // 輸出true,說明其元素拷貝的是引用console.log(arr1[0] === arr3[0]); // 輸出true,說明其元素拷貝的是引用 深拷貝

在堆中重新分配內存,并且把源對象所有屬性都進行新建拷貝,以保證深拷貝的對象的引用圖不包含任何原有對象或對象圖上的任何對象,拷貝后的對象與原來的對象是完全隔離,互不影響。

下面列舉一些深拷貝的例子:

/** * 對象的深拷貝 * JSON.stringify()和JSON.parse() * 這種深拷貝最簡單,但有其局限性,上文已經提到過了 */var obj1 = { name:’wenyuan’, age: 22, social: { blog: ’www.wenyuanblog.com’ }, skills: [’js’, ’html’, ’css’, ’python’]}var obj2 = JSON.parse(JSON.stringify(obj1));console.log(obj1 === obj2) // 輸出false,說明外層數組拷貝的是實例console.log(obj1.social === obj2.social) // 輸出false,說明對于Object類型的屬性也是拷貝實例console.log(obj1.skills === obj2.skills) // 輸出false,說明對于Array類型的屬性也是拷貝實例/** * 對象的深拷貝 * jQuery的 $.extend(true,a,b) */var obj1 = { name:’wenyuan’, age: 22, social: { blog: ’www.wenyuanblog.com’ }, skills: [’js’, ’html’, ’css’, ’python’]}var obj2 = $.extend(true,obj1);console.log(obj1 === obj2) // 輸出false,說明外層數組拷貝的是實例console.log(obj1.social === obj2.social) // 輸出false,說明對于Object類型的屬性也是拷貝實例console.log(obj1.skills === obj2.skills) // 輸出false,說明對于Array類型的屬性也是拷貝實例/** * 對象的深拷貝 * 也可以自己寫一個函數實現,用遞歸+判斷,注意別進入死循環就好 * 這里不舉例了,以前我整理過一篇常用工具類函數的博客,里面包含了深拷貝函數 *//** * 對象的深拷貝 * lodash的_.cloneDeep */var obj1 = { name:’wenyuan’, age: 22, social: { blog: ’www.wenyuanblog.com’ }, skills: [’js’, ’html’, ’css’, ’python’]}var obj2 = _.cloneDeep(obj1);console.log(obj1 === obj2) // 輸出false,說明外層數組拷貝的是實例console.log(obj1.social === obj2.social) // 輸出false,說明對于Object類型的屬性也是拷貝實例console.log(obj1.skills === obj2.skills) // 輸出false,說明對于Array類型的屬性也是拷貝實例

以上就是JavaScript中的淺拷貝與深拷貝的知識點,以代碼的形式記錄下來,方便回顧。

到此這篇關于Vue父子組件傳值的一些坑的文章就介紹到這了,更多相關Vue父子組件傳值內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Vue
相關文章:
主站蜘蛛池模板: 一级毛片无毒不卡直接观看 | 久久无码av三级 | 欧美一级久久久久久久久大 | 成人区视频爽爽爽爽爽 | 午夜成年女人毛片免费观看 | 精品久久久日韩精品成人 | 一级a毛片免费观看 | 99视频精品全部在线播放 | 久久国产精品一区二区三区 | 国产精品亚洲专一区二区三区 | 成人做爰视频www片 成人做爰视频www视频 | 黄色a站| 亚洲一区高清 | 精品成人在线 | 国产一级毛片大陆 | 欧美成人免费夜夜黄啪啪 | 国产片一级片 | 精品日韩欧美一区二区三区在线播放 | 毛片一级在线观看 | 我要看三级毛片 | 亚洲国产精品二区久久 | 国产高清美女一级a毛片久久w | 亚洲欧洲一区 | 午夜视频一区二区三区 | 中文字幕免费观看 | 男女男精品视频在线播放 | 欧美激情性色生活片在线观看 | 萌白酱粉嫩jk福利视频在线观看 | 91精品国产综合成人 | 久草在线新视频 | 国产精品伦理久久久久 | 国产一二三区视频 | 久久精品一区二区三区日韩 | 久久精品视频网 | 亚洲精品99久久久久中文字幕 | 欧美aaaaa一级毛片在线 | 丰满寡妇一级毛片 | a级片在线免费观看 | 黄色毛片三级 | 在线观看一区二区三区四区 | 欧美人交性视频在线香蕉 |