一、問題描述
項目里新添加了一個多選的功能,其顯示的數據都是從后端返回過來的,通過for循環顯示出來。我們需要在返回來的數據外再額外添加一個是否選中的標記,我的選擇是在返回正確的數據時將是都選擇的標記添加進去,然后push到數組中。
在測試的時候出現了bug,即任意勾選其中一條數據都會導致其他的數據一起被勾選,而且其他顯示的內容如果改變了,也會全部改變。原本以為是select選擇器寫的有問題,就把數據全部改成了測試的固定數據,發現並不會出現問題,才開始懷疑是不是由於所有的數據都指向同一個內存導致的。
二、問題代碼
<!--通過循環數組將返回來的對象顯示出來--> <template v-for="(list, index ) in prodCategoryListShow"> <showdiv :key="index" :iskey="index" @click="del" :prodCategory="list.prodCategory" :prodType="list.prodType" :level="list.level" :period="list.period" :reftRate="list.reftRate" :isChecked="list.isChecked" ></showdiv> </template>
錯誤代碼:
//在data中定義對象 data () { return { prodCategoryOneShow: {} } }
//請求回來后判斷是否成功,成功后將數據放入data中定義的對象里 if (res.data.resCode === AjaxReturnState.success) { this.prodCategoryOneShow.prodCategory = res.data.data.prodCategory; this.prodCategoryOneShow.prodType = res.data.data.prodType; this.prodCategoryOneShow.level = res.data.data.level; this.prodCategoryOneShow.period = res.data.data.period; this.prodCategoryOneShow.reftRate = res.data.data.reftRate; //在對象里添加是否選中的標志isChecked,一進去默認未選中 this.prodCategoryOneShow.isChecked = false; //將每次請求回來的一個對象添加到數組里 this.prodCategoryListShow.push(this.prodCategoryOneShow); }
錯誤分析:每一次請求后,我將得到的對象屬性的值一條一條塞進prodCategoryOneShow對象里。由於拿到是基本類型,將基本類型的值一條一條的放入對象里,這樣導致的結果是,我每一次請求后塞進的prodCategoryOneShow對象都指向的是同一個內存地址,而且數據都是一樣的(地址指向即第一次在data中申明的prodCategoryListShow的內存)。所以,我對數組里的任何一個對象進行操作,都會影響到其他的對象的內容。
三、解決方案
if (res.data.resCode === AjaxReturnState.success) { //直接將請求回來的數據賦值給data里的對象 this.prodCategoryOneShow = res.data.data; this.prodCategoryOneShow.isChecked = false; this.prodCategoryListShow.push(this.prodCategoryOneShow); }
這樣子修改后,每一次請求成功后,將data對象簡單賦值給prodCategoryOneShow,prodCategoryOneShow的內存地址指向和data保持一致。因為每一次請求后得到的對象(res.data.data)地址指向都不同,所以將其賦值給data中的對象,每一次的值西也不同,繼而對數組中的對象任意對象操作不會影響到其他對象。
四、其他方案
對象間的賦值(深拷貝)
obj1=JSON.parse(JSON.stringify(obj2));
首先將obj2對象利用JSON.stringify()方法轉換成字符串去掉對象屬性,再使用JSON.parse()方法轉換成對象賦值;
其作用是避免對象直接賦值造成指向相同地址以至於相互影響的問題。