項目中遇到的一個小功能,原來的開發的寫法可能有點冗餘了,擴展性不高,又出了點小bug,特此回來本身寫個相似的小demo,遇到的一些問題記錄一下。
大概這樣html
開始前必定思考下這個怎麼實現會比較好,項目用的vue,拋棄本來的jquery,基於vue的數據驅動去作,響應式這塊vue幫咱們作好了。vue
下面是html的寫法,一個v-for去實現頁面jquery
<div> <div style="text-align:left"> <button style="width:100px;margin-left: 50px;margin-bottom:20px;" @click="add">add</button> </div> <table class="v-table"> <tr class='tr'> <th> name </th> <th> delete </th> </tr> <tr class='v-tr' v-for=" (msg,index) in dataList"> <td> <select name="network" @change='change(msg,index)' v-model="msg.id"> <option v-for="text in msg.list" :value="text.id">{{text.name}}</option> </select> </td> <td> <button @click='deleteTr(msg,index)'>delete</button> </td> </tr> </table> </div>
表格的數據是 dataList,數據結構這樣數組
dataList:[ { id:'a',//作提交時須要,當前行數據的id list:[//name 列select的option數據 { name:'a', id:'a' }, { name:'b', id:'b' }, { name:'c', id:'c' }, { name:'d', id:'d' }, ] } ]
這裏是最簡單的結構了數據結構
而後通常咱們在初始化的時候向後臺請求到初始的數據,就是dataList中的list,我這裏設定的假數據這樣性能
resource:[ { name:'a', id:'a' }, { name:'b', id:'b' }, { name:'c', id:'c' }, { name:'d', id:'d' }, ]
init(){ let resource=_.cloneDeep(this.resource) let obj={ list:resource, id:resource[0].id }; this.dataList=[]; this.dataList.push(obj); }
這裏出現了深拷貝,由於咱們的數據結構是引用類型嵌套引用類型,這裏若是不深拷貝,那下面我對dataList中的項進行更改時,this.resource也會被更改。這個demo裏,this.resource是不能夠被污染更改的。這也是坑之一了學習
add(){ let that=this; //新建條數限制 if(that.dataList.length>=that.resource.length){ return false } //深拷貝數據 let allData=_.cloneDeep(that.resource); // 新增時,判斷已經建立的數據,而後先在對應的數據裏刪除 //這裏對allData進行了操做,splice操做會直接更改原數組,而且allData是外層循環,若是先splice後,再循環內層,在運行 [i].id這個操做時會報錯 //allData是複製出來的源數組,dataList是表格內的數組 for(let i=0;i<that.dataList.length;i++){ for(let j =0;j<allData.length; j++){ if(that.dataList[i].id===allData[j].id){ allData.splice(j,1) } }; }; //推入一組數據 let obj={ list:allData, id:allData[0].id }; that.dataList.push(obj); //把全部已選的數據單獨放置到一個arr數組裏 let arr=[]; for(let k=0,len=that.dataList.length;k<len;k++){ arr.push(that.dataList[k].id); }; //在dataList的list項中刪除全部的已選數據 for(let o =0; o<that.dataList.length; o++){ for(let u =0; u<arr.length; u++){ for(let p=0; p<that.dataList[o].list.length; p++){ if(arr[u]==that.dataList[o].list[p].id){ that.dataList[o].list.splice(p,1); } }; }; }; //dataList的list項中將自身的id對應的數據推入 for(let r =0; r<that.resource.length; r++){ for(let e =0; e<that.dataList.length; e++){ if(that.resource[r].id==that.dataList[e].id){ that.dataList[e].list.unshift(that.resource[r]); } }; }; },
這裏除去深拷貝的坑,還有一個是 若是在嵌套循環中須要更改數組(例如splice方法),那麼須要被更改的數組必定最後一個被嵌套循環。不然在一些判斷條件裏會出錯.優化
deleteTr(msg,index){ let that=this; if(that.dataList.length<=1){ return false; } //先直接刪除,去掉對應數據 that.dataList.splice(index,1); //處理對應數據裏下拉框裏的數據 //複製一份源數據 let allData=_.cloneDeep(that.resource); let obj={}; //遍歷找出刪掉的是數組裏的哪一個數據,而後吧他給obj for(let i=0,len=allData.length; i<len; i++){ if(msg.id===allData[i].id){ obj=allData[i] } }; //循環dataList,將刪除的數據推動dataList的list裏面 for(let o =0; o<that.dataList.length; o++){ that.dataList[o].list.push(obj); }; },
這裏正常刪除再添加this
change(msg,index){ let that=this; //更改dataList中的list //把全部已選的數據單獨放置到一個arr數組裏 let arr=[]; for(let k=0,len=that.dataList.length;k<len;k++){ arr.push(that.dataList[k].id); }; //在dataList的list項中刪除全部的已選數據 for(let o =0; o<that.dataList.length; o++){ that.dataList[o].list=_.cloneDeep(that.resource); for(let u =0; u<arr.length; u++){ for(let p=0; p<that.dataList[o].list.length; p++){ if(arr[u]==that.dataList[o].list[p].id){ that.dataList[o].list.splice(p,1); } }; }; }; //dataList的list項中將自身的id對應的數據推入 for(let r =0; r<that.resource.length; r++){ for(let e =0; e<that.dataList.length; e++){ if(that.resource[r].id==that.dataList[e].id){ that.dataList[e].list.unshift(that.resource[r]); } }; }; }
這裏我把select的v-model設置成msg.id,這樣每次切換時id會自動變化。spa
// let allData=_.cloneDeep(that.resource); for(let i =0,len=that.dataList.length; i<len; i++){ that.dataList[i].list=_.cloneDeep(that.resource); };
這一段最開始也錯了,開始是註釋的那行。
dataList裏的每一個list都須要獨立的內存地址,因此這裏須要循環深拷貝。
剛剛寫完代碼,測了下功能沒有問題就來記錄了,代碼尚未迭代優化,本身也沒有想到更好的處理數據的方法,可是總以爲本身這個嵌套着的循環性能有些低下了。
會優化一下代碼
剛回看一下就發現很多須要改的地方。不過須要休息了,下次編輯一下
平常鼓勵本身。。。
這樣的表格也的確不適合數據量大的狀況,數據量大的狀況須要換一下實現思路。
msl比賽1:1時開始寫功能,寫完看下朋友圈,md好像錯過了什麼。