我说今晚月光那么美,你说是的

image

记录一次反人类的爬坑之路。。

前言

盼望着,盼望着,老大来了,需求的脚步近了。。。

在我接触的前端表格中(例:邮箱)分页全选是有的,而且操作都是在当前页操作(比如全选当前分页的list然后删除),且切换分页的时候上一分页选中的数据则不保留。但是,我们做的这个分页那就不一样了,既要能全部分

页都要一键全选而且点击别的分页还要保留之前一页选中的list并且返回点击还要恢复选中的样式(分页单独查询)。wtf????

开始

听到这话的五分钟里,脑海中浮现了一个删库跑路的念头,然后离职就可以尽情嗨皮,岂不美滋滋。

emmmmm 回头看了看钱包一秒回到现实。。。

静下心来,仔细一想。写一个缓存数据的id数组,然后每次分页查询的时候对比这个数组,如果返回的数据能和这个id数组匹配到的话就绑定样式。至于全选,模拟一下分页的请求然后全部填到id数组。。。

好像给我十分钟我也能搞定的样子。然后事实并没有那么简单。。。

初步入坑

因为用的elementUI框架,所以有自带的触发选择的回调事件,并且变化后选择的数据都给你返回了:

1
2
3
select(data){ 
this.selection = data;
},

对于对比是否选中了某一行,elementUI也给你集成了切换选中状态的事件:

1
this.$refs.some-ref.toggleRowSelection(row,true); //模拟选中

不过切换选中状态的时候要配合this.$nextTick使用,别问我怎么知道的看这部分的小标题。。

写到这里感觉已经万事具备了。

正式入坑

首先准备一个id数组在这里就叫articlelist_selectIdArr然后每次选中状态变化时把idpush到里面:

1
2
3
4
select(data){ 
this.articlelist_selectIdArr = []; //初始化数组
data.forEach(item => this.articlelist_selectIdArr.push(item.id))
},

然后再切换分页的时候toggleRowSelection

1
2
3
4
5
pageChange(){ 
.... //分页查询的数据业务处理
this.$nextTick(() => this.$refs.some-ref.toggleRowSelection(row,true))
...
},

满怀信心测试一波然后。。问题来了

发现选中添加后然后分页切换回来之前分页的数据则没有保留。 找了一下原因是因为toggleRowSelection的时候还会触发切换选中状态的事件也就是又初始化id数组了所以数组永远空值。

然后就改一下select:

1
2
3
4
5
select(data){ 
//this.articlelist_selectIdArr = []; //初始化数组
data.forEach(item => this.articlelist_selectIdArr.push(item.id))
this.articlelist_selectIdArr = [...this.articlelist_selectIdArr] //去重
},

这次发现分页切换回来数据已经保留了,但是新问题来了,你取消选择的时候id数组其实并没有执行删除操作而是在之前的基础上又加了这次选择变化后的数据。所以我脑子一抽又想到了个办法就是在点击checkbox添加一个flag并且同时改变flag状态为false此时就可以再重新初始化数组,如果点击分页查询操作的时候再设为true这样就保留之前的id数组:

1
2
3
4
5
6
7
8
9
10
11
select(data){ 
if(!this.flag) this.articlelist_selectIdArr = []; //初始化数组
data.forEach(item => this.articlelist_selectIdArr.push(item.id))
},

pageChange(){
.... //分页查询的数据业务处理
this.flag = true;
this.$nextTick(() => this.$refs.some-ref.toggleRowSelection(row,true))
...
},

这次确实能保证返回分页数据保留并且取消选中时能重新响应“当前页面选中的id”,但是!!!!! 响应的只是当前页面的选中数据,因为select函数的data只是当前页面的选中数据,也就意味着如果你全选了1,2,3页的数据然后再第一页取消全选的时候,也就是flag为false的时候你已经又把数组初始化了也就是意味着二三页的数据又没了。。。。

现在只能用两个字来形容我现在的思路—————-“僵硬”

重整思路

在前面尝试的几种方案后发现确实有的问题还cover不到。重新理了一下,觉得是我的维护数组的方式有问题,不能准确的响应到那一个id选择状态发生了变化(因为select返回的总是选择变化后的数据);所以我要准确的找到数组的哪一项发生了变化,也就是监听select的data,查看是否增加选中、是否取消选中、是否切换页面操作、是否当前页面的操作。然后再分别对应数组的增删:

select(data){ 
  this.selectDATA = data; //绑定监听
}

pageChange(){  //无变化
  .... //分页查询的数据业务处理
  this.flag = true;
  this.$nextTick(() => this.$refs.some-ref.toggleRowSelection(row,true))
  ...
}

//监听变化
watch:{
        selectDATA:{ 
            handler(newVal,oldVal){

                if(this.flag) return //判断是不是切换分页操作 切换分页对id数组无影响, 只是依赖id数组来切换选中行而已

                let newIdArr = [],oldIdArr = [];
                    newVal.forEach(i => newIdArr.push(i.id))//新的数组id
                    oldVal.forEach(i => oldIdArr.push(i.id))//旧的数组id

                if(newVal.length > oldVal.length){ //此时是选中操作  
                    let result = newIdArr.filter(i => !new Set(oldIdArr).has(i))// newIdArr减oldIdArr的差集
                    this.articlelist_selectIdArr.push(...result) //维护数组
                };
                if(newVal.length < oldVal.length){ //此时是取消选中操作
                    let result = oldIdArr.filter(i => !new Set(newIdArr).has(i))// oldIdArr减newIdArr的差集
                    result.forEach(i => {
                        this.articlelist_selectIdArr = this.articlelist_selectIdArr.filter(item => item != i) //维护数组
                    })   
                }

            },
            deep:true
        }
    }

经测试没啥问题,全选就简单了分页获取然后挨个push。搞定!

总结

想起了初中数学老师一句话:没有困难,制造困难也要上。 挖坑填坑是程序猿的必经之路,共勉。。。