一个增删改功能的表格小demo


项目中遇到的一个小功能,原来的开发的写法可能有点冗余了,扩展性不高,又出了点小bug,特此回来自己写个类似的小demo,遇到的一些问题记录一下。
大概这样

  • 一个操作保留在本地的一个小表格(简化样式了)
  • 请求的数据是所有的 name 列的数据
  • name列是个select,option会随着表格数据的增加而改变,也就是option不会和列表数据重复
  • 三个主要方法,add,delete,change。因为最近想学习下lodash,深拷贝用的 _.cloneDeep()

    一个增删改功能的表格小demo

设计

开始前一定思考下这个怎么实现会比较好,项目用的vue,抛弃原本的jquery,基于vue的数据驱动去做,响应式这块vue帮我们做好了。

下面是html的写法,一个v-for去实现页面

 <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

 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方法),那么需要被更改的数组一定最后一个被嵌套循环。否则在一些判断条件里会出错.

delete

        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);
            };
         },

这里正常删除再添加

change

        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会自动变化。

 //         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好像错过了什么。


发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>